Delete base unittests and build files
Change-Id: I734ea94edff2974d8ebe5c990bbd18233e9ce356
Reviewed-on: https://gn-review.googlesource.com/1403
Reviewed-by: Brett Wilson <brettw@chromium.org>
diff --git a/base/BUILD.gn b/base/BUILD.gn
deleted file mode 100644
index 28542b2..0000000
--- a/base/BUILD.gn
+++ /dev/null
@@ -1,3164 +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.
-
-# HOW TO WRITE CONDITIONALS IN THIS FILE
-# ======================================
-#
-# In many other places, one would write a conditional that expresses all the
-# cases when a source file is used or unused, and then either add or subtract
-# it from the sources list in that case
-#
-# Since base includes so many low-level things that vary widely and
-# unpredictably for the various build types, we prefer a slightly different
-# style. Instead, there are big per-platform blocks of inclusions and
-# exclusions. If a given file has an inclusion or exclusion rule that applies
-# for multiple conditions, prefer to duplicate it in both lists. This makes it
-# a bit easier to see which files apply in which cases rather than having a
-# huge sequence of random-looking conditionals.
-
-import("//build/buildflag_header.gni")
-import("//build/config/allocator.gni")
-import("//build/config/arm.gni")
-import("//build/config/c++/c++.gni")
-import("//build/config/chromecast_build.gni")
-import("//build/config/compiler/compiler.gni")
-import("//build/config/dcheck_always_on.gni")
-import("//build/config/jumbo.gni")
-import("//build/config/nacl/config.gni")
-import("//build/config/sysroot.gni")
-import("//build/config/ui.gni")
-import("//build/nocompile.gni")
-import("//testing/libfuzzer/fuzzer_test.gni")
-import("//testing/test.gni")
-
-declare_args() {
- # Override this value to give a specific build date.
- # See //base/build_time.cc and //build/write_build_date_header.py for more
- # details and the expected format.
- override_build_date = "N/A"
-
- # Indicates if the Location object contains the source code information
- # (file, function, line). False means only the program counter (and currently
- # file name) is saved.
- enable_location_source = true
-
- # Unsafe developer build. Has developer-friendly features that may weaken or
- # disable security measures like sandboxing or ASLR.
- # IMPORTANT: Unsafe developer builds should never be distributed to end users.
- is_unsafe_developer_build = !is_official_build
-
- # Set to true to disable COM init check hooks.
- com_init_check_hook_disabled = false
-
- # Set to true to enable mutex priority inheritance. See the comments in
- # LockImpl::PriorityInheritanceAvailable() in lock_impl_posix.cc for the
- # platform requirements to safely enable priority inheritance.
- enable_mutex_priority_inheritance = false
-}
-
-# Determines whether libevent should be dep.
-dep_libevent = !is_fuchsia && !is_win && !(is_nacl && !is_nacl_nonsfi)
-
-# Determines whether message_pump_libevent should be used.
-use_libevent = dep_libevent && !is_ios
-
-if (is_android) {
- import("//build/config/android/rules.gni")
-}
-
-if (is_fuchsia) {
- import("//third_party/fuchsia-sdk/fidl_library.gni")
-}
-
-config("base_flags") {
- if (is_clang) {
- cflags = [
- # Don't die on dtoa code that uses a char as an array index.
- # This is required solely for base/third_party/dmg_fp/dtoa_wrapper.cc.
- "-Wno-char-subscripts",
-
- # Ideally all product code (but no test code) in chrome would have these
- # flags. But this isn't trivial so start with //base as a minimum
- # requirement.
- # https://groups.google.com/a/chromium.org/d/topic/chromium-dev/B9Q5KTD7iCo/discussion
- "-Wglobal-constructors",
- "-Wexit-time-destructors",
- ]
- }
-}
-
-config("base_implementation") {
- defines = [ "BASE_IMPLEMENTATION" ]
- configs = [ "//build/config/compiler:wexit_time_destructors" ]
-}
-
-if (is_win) {
- # This is in a separate config so the flags can be applied to dependents.
- # ldflags in GN aren't automatically inherited.
- config("base_win_linker_flags") {
- ldflags = [
- "/DELAYLOAD:cfgmgr32.dll",
- "/DELAYLOAD:powrprof.dll",
- "/DELAYLOAD:setupapi.dll",
- ]
- }
-}
-
-if (is_nacl_nonsfi) {
- # Must be in a config because of how GN orders flags (otherwise -Wall will
- # appear after this, and turn it back on).
- config("nacl_nonsfi_warnings") {
- # file_util_posix.cc contains a function which is not
- # being used by nacl_helper_nonsfi.
- cflags = [ "-Wno-unused-function" ]
- }
-}
-
-if (is_android) {
- config("android_system_libs") {
- libs = [ "log" ] # Used by logging.cc.
- }
-}
-
-# Base and everything it depends on should be a static library rather than
-# a source set. Base is more of a "library" in the classic sense in that many
-# small parts of it are used in many different contexts. This combined with a
-# few static initializers floating around means that dead code stripping
-# still leaves a lot of code behind that isn't always used. For example, this
-# saves more than 40K for a smaller target like chrome_elf.
-#
-# Use static libraries for the helper stuff as well like //base/debug since
-# those things refer back to base code, which will force base compilation units
-# to be linked in where they wouldn't have otherwise. This does not include
-# test code (test support and anything in the test directory) which should use
-# source_set as is recommended for GN targets).
-jumbo_component("base") {
- if (is_nacl_nonsfi) {
- # TODO(phosek) bug 570839: If field_trial.cc is in a static library,
- # nacl_helper_nonsfi doesn't link properly on Linux in debug builds. The
- # reasons for this seem to involve obscure toolchain bugs. This should be
- # fixed and this target should always be a static_library in the
- # non-component case.
- static_component_type = "source_set"
- }
- if (is_nacl || is_ios) {
- # Link errors related to malloc functions if libbase for nacl is
- # compiled with jumbo: https://crbug.com/775959.
- # Same for ios: https://crbug.com/776313.
- never_build_jumbo = true
- }
-
- sources = [
- "allocator/allocator_check.cc",
- "allocator/allocator_check.h",
- "allocator/allocator_extension.cc",
- "allocator/allocator_extension.h",
- "allocator/allocator_interception_mac.h",
- "allocator/allocator_interception_mac.mm",
- "allocator/allocator_shim.h",
- "allocator/malloc_zone_functions_mac.cc",
- "allocator/malloc_zone_functions_mac.h",
- "android/android_hardware_buffer_abi.h",
- "android/android_hardware_buffer_compat.cc",
- "android/android_hardware_buffer_compat.h",
- "android/animation_frame_time_histogram.cc",
- "android/apk_assets.cc",
- "android/apk_assets.h",
- "android/application_status_listener.cc",
- "android/application_status_listener.h",
- "android/base_jni_onload.cc",
- "android/base_jni_onload.h",
- "android/build_info.cc",
- "android/build_info.h",
- "android/callback_android.cc",
- "android/callback_android.h",
- "android/child_process_service.cc",
- "android/command_line_android.cc",
- "android/content_uri_utils.cc",
- "android/content_uri_utils.h",
- "android/cpu_features.cc",
- "android/early_trace_event_binding.cc",
- "android/event_log.cc",
- "android/event_log.h",
- "android/field_trial_list.cc",
- "android/important_file_writer_android.cc",
- "android/java_exception_reporter.cc",
- "android/java_exception_reporter.h",
- "android/java_handler_thread.cc",
- "android/java_handler_thread.h",
- "android/java_runtime.cc",
- "android/java_runtime.h",
- "android/jni_android.cc",
- "android/jni_android.h",
- "android/jni_array.cc",
- "android/jni_array.h",
- "android/jni_generator/jni_generator_helper.h",
- "android/jni_int_wrapper.h",
- "android/jni_registrar.cc",
- "android/jni_registrar.h",
- "android/jni_string.cc",
- "android/jni_string.h",
- "android/jni_utils.cc",
- "android/jni_utils.h",
- "android/jni_weak_ref.cc",
- "android/jni_weak_ref.h",
- "android/library_loader/anchor_functions.cc",
- "android/library_loader/anchor_functions.h",
- "android/library_loader/library_load_from_apk_status_codes.h",
- "android/library_loader/library_loader_hooks.cc",
- "android/library_loader/library_loader_hooks.h",
- "android/library_loader/library_prefetcher.cc",
- "android/library_loader/library_prefetcher.h",
- "android/locale_utils.cc",
- "android/locale_utils.h",
- "android/memory_pressure_listener_android.cc",
- "android/memory_pressure_listener_android.h",
- "android/path_service_android.cc",
- "android/path_utils.cc",
- "android/path_utils.h",
- "android/record_histogram.cc",
- "android/record_user_action.cc",
- "android/scoped_hardware_buffer_handle.cc",
- "android/scoped_hardware_buffer_handle.h",
- "android/scoped_java_ref.cc",
- "android/scoped_java_ref.h",
- "android/statistics_recorder_android.cc",
- "android/sys_utils.cc",
- "android/sys_utils.h",
- "android/throw_uncaught_exception.cc",
- "android/throw_uncaught_exception.h",
- "android/time_utils.cc",
- "android/timezone_utils.cc",
- "android/timezone_utils.h",
- "android/trace_event_binding.cc",
- "android/unguessable_token_android.cc",
- "android/unguessable_token_android.h",
- "at_exit.cc",
- "at_exit.h",
- "atomic_ref_count.h",
- "atomic_sequence_num.h",
- "atomicops.h",
- "atomicops_internals_atomicword_compat.h",
- "atomicops_internals_portable.h",
- "atomicops_internals_x86_msvc.h",
- "auto_reset.h",
- "barrier_closure.cc",
- "barrier_closure.h",
- "base64.cc",
- "base64.h",
- "base64url.cc",
- "base64url.h",
- "base_export.h",
- "base_switches.h",
- "big_endian.cc",
- "big_endian.h",
- "bind.h",
- "bind_helpers.h",
- "bind_internal.h",
- "bit_cast.h",
- "bits.h",
- "build_time.cc",
- "build_time.h",
- "callback.h",
- "callback_forward.h",
- "callback_helpers.cc",
- "callback_helpers.h",
- "callback_internal.cc",
- "callback_internal.h",
- "callback_list.h",
- "cancelable_callback.h",
- "command_line.cc",
- "command_line.h",
- "compiler_specific.h",
- "component_export.h",
- "containers/adapters.h",
- "containers/circular_deque.h",
- "containers/flat_map.h",
- "containers/flat_set.h",
- "containers/flat_tree.h",
- "containers/hash_tables.h",
- "containers/id_map.h",
- "containers/linked_list.h",
- "containers/mru_cache.h",
- "containers/small_map.h",
- "containers/span.h",
- "containers/stack.h",
- "containers/stack_container.h",
- "containers/unique_ptr_adapters.h",
- "containers/vector_buffer.h",
- "cpu.cc",
- "cpu.h",
- "critical_closure.h",
- "critical_closure_internal_ios.mm",
-
- # This file depends on files from the "debug/allocator" target,
- # but this target does not depend on "debug/allocator".
- "debug/activity_analyzer.cc",
- "debug/activity_analyzer.h",
- "debug/activity_tracker.cc",
- "debug/activity_tracker.h",
- "debug/alias.cc",
- "debug/alias.h",
- "debug/asan_invalid_access.cc",
- "debug/asan_invalid_access.h",
- "debug/close_handle_hook_win.cc",
- "debug/close_handle_hook_win.h",
- "debug/crash_logging.cc",
- "debug/crash_logging.h",
- "debug/debugger.cc",
- "debug/debugger.h",
- "debug/debugger_win.cc",
- "debug/dump_without_crashing.cc",
- "debug/dump_without_crashing.h",
- "debug/gdi_debug_util_win.cc",
- "debug/gdi_debug_util_win.h",
- "debug/leak_annotations.h",
- "debug/leak_tracker.h",
- "debug/proc_maps_linux.cc",
- "debug/proc_maps_linux.h",
- "debug/profiler.cc",
- "debug/profiler.h",
- "debug/stack_trace.cc",
- "debug/stack_trace.h",
- "debug/stack_trace_android.cc",
- "debug/stack_trace_win.cc",
- "debug/task_annotator.cc",
- "debug/task_annotator.h",
- "debug/thread_heap_usage_tracker.cc",
- "debug/thread_heap_usage_tracker.h",
- "deferred_sequenced_task_runner.cc",
- "deferred_sequenced_task_runner.h",
- "environment.cc",
- "environment.h",
- "export_template.h",
- "feature_list.cc",
- "feature_list.h",
- "file_descriptor_store.cc",
- "file_descriptor_store.h",
- "file_version_info.h",
- "file_version_info_mac.h",
- "file_version_info_mac.mm",
- "file_version_info_win.cc",
- "file_version_info_win.h",
- "files/dir_reader_fallback.h",
- "files/dir_reader_linux.h",
- "files/file.cc",
- "files/file.h",
- "files/file_enumerator.cc",
- "files/file_enumerator.h",
- "files/file_enumerator_win.cc",
- "files/file_path.cc",
- "files/file_path.h",
- "files/file_path_constants.cc",
- "files/file_path_watcher.cc",
- "files/file_path_watcher.h",
- "files/file_path_watcher_fsevents.cc",
- "files/file_path_watcher_fsevents.h",
- "files/file_path_watcher_kqueue.cc",
- "files/file_path_watcher_kqueue.h",
- "files/file_path_watcher_linux.cc",
- "files/file_path_watcher_mac.cc",
- "files/file_path_watcher_win.cc",
- "files/file_proxy.cc",
- "files/file_proxy.h",
- "files/file_tracing.cc",
- "files/file_tracing.h",
- "files/file_util.cc",
- "files/file_util.h",
- "files/file_util_android.cc",
- "files/file_util_linux.cc",
- "files/file_util_mac.mm",
- "files/file_util_win.cc",
- "files/file_win.cc",
- "files/important_file_writer.cc",
- "files/important_file_writer.h",
- "files/memory_mapped_file.cc",
- "files/memory_mapped_file.h",
- "files/memory_mapped_file_win.cc",
- "files/platform_file.h",
- "files/scoped_file.cc",
- "files/scoped_file.h",
- "files/scoped_temp_dir.cc",
- "files/scoped_temp_dir.h",
- "format_macros.h",
- "gtest_prod_util.h",
- "guid.cc",
- "guid.h",
- "hash.cc",
- "hash.h",
- "ios/block_types.h",
- "ios/crb_protocol_observers.h",
- "ios/crb_protocol_observers.mm",
- "ios/device_util.h",
- "ios/device_util.mm",
- "ios/ios_util.h",
- "ios/ios_util.mm",
- "ios/ns_error_util.h",
- "ios/ns_error_util.mm",
- "ios/scoped_critical_action.h",
- "ios/scoped_critical_action.mm",
- "ios/weak_nsobject.h",
- "ios/weak_nsobject.mm",
- "json/json_file_value_serializer.cc",
- "json/json_file_value_serializer.h",
- "json/json_parser.cc",
- "json/json_parser.h",
- "json/json_reader.cc",
- "json/json_reader.h",
- "json/json_string_value_serializer.cc",
- "json/json_string_value_serializer.h",
- "json/json_value_converter.cc",
- "json/json_value_converter.h",
- "json/json_writer.cc",
- "json/json_writer.h",
- "json/string_escape.cc",
- "json/string_escape.h",
- "lazy_instance.h",
- "lazy_instance_helpers.cc",
- "lazy_instance_helpers.h",
- "linux_util.cc",
- "linux_util.h",
- "location.cc",
- "location.h",
- "logging.cc",
- "logging.h",
- "logging_win.cc",
- "logging_win.h",
- "mac/authorization_util.h",
- "mac/authorization_util.mm",
- "mac/availability.h",
- "mac/bind_objc_block.h",
- "mac/bundle_locations.h",
- "mac/bundle_locations.mm",
- "mac/call_with_eh_frame.cc",
- "mac/call_with_eh_frame.h",
- "mac/call_with_eh_frame_asm.S",
- "mac/close_nocancel.cc",
- "mac/dispatch_source_mach.cc",
- "mac/dispatch_source_mach.h",
- "mac/foundation_util.h",
- "mac/foundation_util.mm",
- "mac/launch_services_util.h",
- "mac/launch_services_util.mm",
- "mac/launchd.cc",
- "mac/launchd.h",
- "mac/mac_logging.h",
- "mac/mac_logging.mm",
- "mac/mac_util.h",
- "mac/mac_util.mm",
- "mac/mach_logging.cc",
- "mac/mach_logging.h",
- "mac/mach_port_broker.h",
- "mac/mach_port_broker.mm",
- "mac/mach_port_util.cc",
- "mac/mach_port_util.h",
- "mac/objc_release_properties.h",
- "mac/objc_release_properties.mm",
- "mac/os_crash_dumps.cc",
- "mac/os_crash_dumps.h",
- "mac/scoped_aedesc.h",
- "mac/scoped_authorizationref.h",
- "mac/scoped_block.h",
- "mac/scoped_cffiledescriptorref.h",
- "mac/scoped_cftyperef.h",
- "mac/scoped_dispatch_object.h",
- "mac/scoped_ionotificationportref.h",
- "mac/scoped_ioobject.h",
- "mac/scoped_ioplugininterface.h",
- "mac/scoped_launch_data.h",
- "mac/scoped_mach_port.cc",
- "mac/scoped_mach_port.h",
- "mac/scoped_mach_vm.cc",
- "mac/scoped_mach_vm.h",
- "mac/scoped_nsautorelease_pool.h",
- "mac/scoped_nsautorelease_pool.mm",
- "mac/scoped_nsobject.h",
- "mac/scoped_nsobject.mm",
- "mac/scoped_objc_class_swizzler.h",
- "mac/scoped_objc_class_swizzler.mm",
- "mac/scoped_sending_event.h",
- "mac/scoped_sending_event.mm",
- "mac/sdk_forward_declarations.h",
- "mac/sdk_forward_declarations.mm",
- "macros.h",
- "md5.cc",
- "md5.h",
- "memory/aligned_memory.cc",
- "memory/aligned_memory.h",
- "memory/discardable_memory.cc",
- "memory/discardable_memory.h",
- "memory/discardable_memory_allocator.cc",
- "memory/discardable_memory_allocator.h",
- "memory/discardable_shared_memory.cc",
- "memory/discardable_shared_memory.h",
- "memory/free_deleter.h",
- "memory/linked_ptr.h",
- "memory/memory_coordinator_client.cc",
- "memory/memory_coordinator_client.h",
- "memory/memory_coordinator_client_registry.cc",
- "memory/memory_coordinator_client_registry.h",
- "memory/memory_coordinator_proxy.cc",
- "memory/memory_coordinator_proxy.h",
- "memory/memory_pressure_listener.cc",
- "memory/memory_pressure_listener.h",
- "memory/memory_pressure_monitor.cc",
- "memory/memory_pressure_monitor.h",
- "memory/memory_pressure_monitor_chromeos.cc",
- "memory/memory_pressure_monitor_chromeos.h",
- "memory/memory_pressure_monitor_mac.cc",
- "memory/memory_pressure_monitor_mac.h",
- "memory/memory_pressure_monitor_win.cc",
- "memory/memory_pressure_monitor_win.h",
- "memory/platform_shared_memory_region.cc",
- "memory/platform_shared_memory_region.h",
- "memory/protected_memory.cc",
- "memory/protected_memory.h",
- "memory/protected_memory_cfi.h",
- "memory/protected_memory_win.cc",
- "memory/ptr_util.h",
- "memory/raw_scoped_refptr_mismatch_checker.h",
- "memory/read_only_shared_memory_region.cc",
- "memory/read_only_shared_memory_region.h",
- "memory/ref_counted.cc",
- "memory/ref_counted.h",
- "memory/ref_counted_delete_on_sequence.h",
- "memory/ref_counted_memory.cc",
- "memory/ref_counted_memory.h",
- "memory/scoped_policy.h",
- "memory/scoped_refptr.h",
- "memory/shared_memory.h",
- "memory/shared_memory_handle.cc",
- "memory/shared_memory_handle.h",
- "memory/shared_memory_helper.cc",
- "memory/shared_memory_helper.h",
- "memory/shared_memory_mapping.cc",
- "memory/shared_memory_mapping.h",
- "memory/shared_memory_tracker.cc",
- "memory/shared_memory_tracker.h",
- "memory/singleton.h",
- "memory/unsafe_shared_memory_region.cc",
- "memory/unsafe_shared_memory_region.h",
- "memory/weak_ptr.cc",
- "memory/weak_ptr.h",
- "memory/writable_shared_memory_region.cc",
- "memory/writable_shared_memory_region.h",
- "message_loop/incoming_task_queue.cc",
- "message_loop/incoming_task_queue.h",
- "message_loop/message_loop.cc",
- "message_loop/message_loop.h",
- "message_loop/message_loop_current.cc",
- "message_loop/message_loop_current.h",
- "message_loop/message_loop_task_runner.cc",
- "message_loop/message_loop_task_runner.h",
- "message_loop/message_pump.cc",
- "message_loop/message_pump.h",
- "message_loop/message_pump_android.cc",
- "message_loop/message_pump_android.h",
- "message_loop/message_pump_default.cc",
- "message_loop/message_pump_default.h",
- "message_loop/message_pump_for_io.h",
- "message_loop/message_pump_for_ui.h",
- "message_loop/message_pump_glib.cc",
- "message_loop/message_pump_glib.h",
- "message_loop/message_pump_io_ios.cc",
- "message_loop/message_pump_io_ios.h",
- "message_loop/message_pump_mac.h",
- "message_loop/message_pump_mac.mm",
- "message_loop/message_pump_win.cc",
- "message_loop/message_pump_win.h",
- "message_loop/timer_slack.h",
- "metrics/bucket_ranges.cc",
- "metrics/bucket_ranges.h",
- "metrics/dummy_histogram.cc",
- "metrics/dummy_histogram.h",
- "metrics/field_trial.cc",
- "metrics/field_trial.h",
- "metrics/field_trial_param_associator.cc",
- "metrics/field_trial_param_associator.h",
- "metrics/field_trial_params.cc",
- "metrics/field_trial_params.h",
- "metrics/histogram.cc",
- "metrics/histogram.h",
- "metrics/histogram_base.cc",
- "metrics/histogram_base.h",
- "metrics/histogram_delta_serialization.cc",
- "metrics/histogram_delta_serialization.h",
- "metrics/histogram_flattener.h",
- "metrics/histogram_functions.cc",
- "metrics/histogram_functions.h",
- "metrics/histogram_macros.h",
- "metrics/histogram_macros_internal.h",
- "metrics/histogram_macros_local.h",
- "metrics/histogram_samples.cc",
- "metrics/histogram_samples.h",
- "metrics/histogram_snapshot_manager.cc",
- "metrics/histogram_snapshot_manager.h",
- "metrics/metrics_hashes.cc",
- "metrics/metrics_hashes.h",
- "metrics/persistent_histogram_allocator.cc",
- "metrics/persistent_histogram_allocator.h",
- "metrics/persistent_memory_allocator.cc",
- "metrics/persistent_memory_allocator.h",
- "metrics/persistent_sample_map.cc",
- "metrics/persistent_sample_map.h",
- "metrics/record_histogram_checker.h",
- "metrics/sample_map.cc",
- "metrics/sample_map.h",
- "metrics/sample_vector.cc",
- "metrics/sample_vector.h",
- "metrics/single_sample_metrics.cc",
- "metrics/single_sample_metrics.h",
- "metrics/sparse_histogram.cc",
- "metrics/sparse_histogram.h",
- "metrics/statistics_recorder.cc",
- "metrics/statistics_recorder.h",
- "metrics/user_metrics.cc",
- "metrics/user_metrics.h",
- "metrics/user_metrics_action.h",
- "native_library.cc",
- "native_library.h",
- "native_library_ios.mm",
- "native_library_mac.mm",
- "native_library_win.cc",
- "nix/mime_util_xdg.cc",
- "nix/mime_util_xdg.h",
- "nix/xdg_util.cc",
- "nix/xdg_util.h",
- "no_destructor.h",
- "observer_list.h",
- "observer_list_threadsafe.cc",
- "observer_list_threadsafe.h",
- "optional.h",
- "os_compat_android.cc",
- "os_compat_android.h",
- "os_compat_nacl.cc",
- "os_compat_nacl.h",
- "path_service.cc",
- "path_service.h",
- "pending_task.cc",
- "pending_task.h",
- "pickle.cc",
- "pickle.h",
- "post_task_and_reply_with_result_internal.h",
- "power_monitor/power_monitor.cc",
- "power_monitor/power_monitor.h",
- "power_monitor/power_monitor_device_source.cc",
- "power_monitor/power_monitor_device_source.h",
- "power_monitor/power_monitor_source.cc",
- "power_monitor/power_monitor_source.h",
- "power_monitor/power_observer.h",
- "process/internal_linux.cc",
- "process/internal_linux.h",
- "process/kill.cc",
- "process/kill.h",
- "process/kill_mac.cc",
- "process/kill_win.cc",
- "process/launch.cc",
- "process/launch.h",
- "process/launch_ios.cc",
- "process/launch_mac.cc",
- "process/launch_win.cc",
- "process/memory.cc",
- "process/memory.h",
- "process/memory_linux.cc",
- "process/memory_mac.mm",
- "process/memory_win.cc",
- "process/port_provider_mac.cc",
- "process/port_provider_mac.h",
- "process/process.h",
- "process/process_handle.cc",
- "process/process_handle.h",
-
- #"process/process_handle_freebsd.cc", # Unused in Chromium build.
- "process/process_handle_linux.cc",
- "process/process_handle_mac.cc",
-
- #"process/process_handle_openbsd.cc", # Unused in Chromium build.
- "process/process_handle_win.cc",
- "process/process_info.h",
- "process/process_info_linux.cc",
- "process/process_info_mac.cc",
- "process/process_info_win.cc",
- "process/process_iterator.cc",
- "process/process_iterator.h",
-
- #"process/process_iterator_freebsd.cc", # Unused in Chromium build.
- "process/process_iterator_linux.cc",
- "process/process_iterator_mac.cc",
-
- #"process/process_iterator_openbsd.cc", # Unused in Chromium build.
- "process/process_iterator_win.cc",
- "process/process_linux.cc",
- "process/process_mac.cc",
- "process/process_metrics.cc",
- "process/process_metrics.h",
-
- #"process/process_metrics_freebsd.cc", # Unused in Chromium build.
- "process/process_metrics_ios.cc",
- "process/process_metrics_linux.cc",
- "process/process_metrics_mac.cc",
-
- #"process/process_metrics_openbsd.cc", # Unused in Chromium build.
- "process/process_metrics_win.cc",
- "process/process_win.cc",
- "profiler/native_stack_sampler.cc",
- "profiler/native_stack_sampler.h",
- "profiler/native_stack_sampler_mac.cc",
- "profiler/native_stack_sampler_win.cc",
- "profiler/stack_sampling_profiler.cc",
- "profiler/stack_sampling_profiler.h",
- "rand_util.cc",
- "rand_util.h",
- "rand_util_nacl.cc",
- "rand_util_win.cc",
- "run_loop.cc",
- "run_loop.h",
- "sampling_heap_profiler/sampling_heap_profiler.cc",
- "sampling_heap_profiler/sampling_heap_profiler.h",
- "scoped_clear_errno.h",
- "scoped_generic.h",
- "scoped_native_library.cc",
- "scoped_native_library.h",
- "scoped_observer.h",
- "sequence_checker.h",
- "sequence_checker_impl.cc",
- "sequence_checker_impl.h",
- "sequence_token.cc",
- "sequence_token.h",
- "sequenced_task_runner.cc",
- "sequenced_task_runner.h",
- "sequenced_task_runner_helpers.h",
- "sha1.cc",
- "sha1.h",
- "single_thread_task_runner.h",
- "stl_util.h",
- "strings/char_traits.h",
- "strings/latin1_string_conversions.cc",
- "strings/latin1_string_conversions.h",
- "strings/nullable_string16.cc",
- "strings/nullable_string16.h",
- "strings/pattern.cc",
- "strings/pattern.h",
- "strings/safe_sprintf.cc",
- "strings/safe_sprintf.h",
- "strings/strcat.cc",
- "strings/strcat.h",
- "strings/string16.cc",
- "strings/string16.h",
- "strings/string_number_conversions.cc",
- "strings/string_number_conversions.h",
- "strings/string_piece.cc",
- "strings/string_piece.h",
- "strings/string_piece_forward.h",
- "strings/string_split.cc",
- "strings/string_split.h",
- "strings/string_tokenizer.h",
- "strings/string_util.cc",
- "strings/string_util.h",
- "strings/string_util_constants.cc",
- "strings/string_util_win.h",
- "strings/stringize_macros.h",
- "strings/stringprintf.cc",
- "strings/stringprintf.h",
- "strings/sys_string_conversions.h",
- "strings/sys_string_conversions_mac.mm",
- "strings/sys_string_conversions_win.cc",
- "strings/utf_offset_string_conversions.cc",
- "strings/utf_offset_string_conversions.h",
- "strings/utf_string_conversion_utils.cc",
- "strings/utf_string_conversion_utils.h",
- "strings/utf_string_conversions.cc",
- "strings/utf_string_conversions.h",
- "supports_user_data.cc",
- "supports_user_data.h",
- "sync_socket.h",
- "sync_socket_win.cc",
- "synchronization/atomic_flag.cc",
- "synchronization/atomic_flag.h",
- "synchronization/cancellation_flag.h",
- "synchronization/condition_variable.h",
- "synchronization/condition_variable_win.cc",
- "synchronization/lock.cc",
- "synchronization/lock.h",
- "synchronization/lock_impl.h",
- "synchronization/lock_impl_win.cc",
- "synchronization/spin_wait.h",
- "synchronization/waitable_event.h",
- "synchronization/waitable_event_mac.cc",
- "synchronization/waitable_event_watcher.h",
- "synchronization/waitable_event_watcher_mac.cc",
- "synchronization/waitable_event_watcher_win.cc",
- "synchronization/waitable_event_win.cc",
- "sys_byteorder.h",
- "sys_info.cc",
- "sys_info.h",
- "sys_info_android.cc",
- "sys_info_chromeos.cc",
- "sys_info_internal.h",
- "syslog_logging.cc",
- "syslog_logging.h",
-
- #"sys_info_freebsd.cc", # Unused in Chromium build.
- "sys_info_ios.mm",
- "sys_info_linux.cc",
- "sys_info_mac.mm",
-
- #"sys_info_openbsd.cc", # Unused in Chromium build.
- "sys_info_win.cc",
- "system_monitor/system_monitor.cc",
- "system_monitor/system_monitor.h",
- "task/cancelable_task_tracker.cc",
- "task/cancelable_task_tracker.h",
- "task_runner.cc",
- "task_runner.h",
- "task_runner_util.h",
- "task_scheduler/can_schedule_sequence_observer.h",
- "task_scheduler/delayed_task_manager.cc",
- "task_scheduler/delayed_task_manager.h",
- "task_scheduler/environment_config.cc",
- "task_scheduler/environment_config.h",
- "task_scheduler/initialization_util.cc",
- "task_scheduler/initialization_util.h",
- "task_scheduler/lazy_task_runner.cc",
- "task_scheduler/lazy_task_runner.h",
- "task_scheduler/platform_native_worker_pool_win.cc",
- "task_scheduler/platform_native_worker_pool_win.h",
- "task_scheduler/post_task.cc",
- "task_scheduler/post_task.h",
- "task_scheduler/priority_queue.cc",
- "task_scheduler/priority_queue.h",
- "task_scheduler/scheduler_lock.h",
- "task_scheduler/scheduler_lock_impl.cc",
- "task_scheduler/scheduler_lock_impl.h",
- "task_scheduler/scheduler_single_thread_task_runner_manager.cc",
- "task_scheduler/scheduler_single_thread_task_runner_manager.h",
- "task_scheduler/scheduler_worker.cc",
- "task_scheduler/scheduler_worker.h",
- "task_scheduler/scheduler_worker_observer.h",
- "task_scheduler/scheduler_worker_params.h",
- "task_scheduler/scheduler_worker_pool.cc",
- "task_scheduler/scheduler_worker_pool.h",
- "task_scheduler/scheduler_worker_pool_impl.cc",
- "task_scheduler/scheduler_worker_pool_impl.h",
- "task_scheduler/scheduler_worker_pool_params.cc",
- "task_scheduler/scheduler_worker_pool_params.h",
- "task_scheduler/scheduler_worker_stack.cc",
- "task_scheduler/scheduler_worker_stack.h",
- "task_scheduler/scoped_set_task_priority_for_current_thread.cc",
- "task_scheduler/scoped_set_task_priority_for_current_thread.h",
- "task_scheduler/sequence.cc",
- "task_scheduler/sequence.h",
- "task_scheduler/sequence_sort_key.cc",
- "task_scheduler/sequence_sort_key.h",
- "task_scheduler/service_thread.cc",
- "task_scheduler/service_thread.h",
- "task_scheduler/single_thread_task_runner_thread_mode.h",
- "task_scheduler/task.cc",
- "task_scheduler/task.h",
- "task_scheduler/task_scheduler.cc",
- "task_scheduler/task_scheduler.h",
- "task_scheduler/task_scheduler_impl.cc",
- "task_scheduler/task_scheduler_impl.h",
- "task_scheduler/task_tracker.cc",
- "task_scheduler/task_tracker.h",
- "task_scheduler/task_traits.cc",
- "task_scheduler/task_traits.h",
- "task_scheduler/task_traits_details.h",
- "task_scheduler/tracked_ref.h",
- "template_util.h",
- "test/malloc_wrapper.h",
- "third_party/dmg_fp/dmg_fp.h",
- "third_party/dmg_fp/dtoa_wrapper.cc",
- "third_party/dmg_fp/g_fmt.cc",
- "third_party/icu/icu_utf.cc",
- "third_party/icu/icu_utf.h",
- "third_party/nspr/prtime.cc",
- "third_party/nspr/prtime.h",
- "third_party/superfasthash/superfasthash.c",
- "thread_annotations.h",
- "threading/platform_thread.h",
- "threading/platform_thread_android.cc",
- "threading/platform_thread_linux.cc",
- "threading/platform_thread_mac.mm",
- "threading/platform_thread_win.cc",
- "threading/post_task_and_reply_impl.cc",
- "threading/post_task_and_reply_impl.h",
- "threading/scoped_blocking_call.cc",
- "threading/scoped_blocking_call.h",
- "threading/sequence_local_storage_map.cc",
- "threading/sequence_local_storage_map.h",
- "threading/sequence_local_storage_slot.cc",
- "threading/sequence_local_storage_slot.h",
- "threading/sequenced_task_runner_handle.cc",
- "threading/sequenced_task_runner_handle.h",
- "threading/simple_thread.cc",
- "threading/simple_thread.h",
- "threading/thread.cc",
- "threading/thread.h",
- "threading/thread_checker.h",
- "threading/thread_checker_impl.cc",
- "threading/thread_checker_impl.h",
- "threading/thread_collision_warner.cc",
- "threading/thread_collision_warner.h",
- "threading/thread_id_name_manager.cc",
- "threading/thread_id_name_manager.h",
- "threading/thread_local.h",
- "threading/thread_local_storage.cc",
- "threading/thread_local_storage.h",
- "threading/thread_local_storage_win.cc",
- "threading/thread_restrictions.cc",
- "threading/thread_restrictions.h",
- "threading/thread_task_runner_handle.cc",
- "threading/thread_task_runner_handle.h",
- "threading/watchdog.cc",
- "threading/watchdog.h",
- "time/clock.cc",
- "time/clock.h",
- "time/default_clock.cc",
- "time/default_clock.h",
- "time/default_tick_clock.cc",
- "time/default_tick_clock.h",
- "time/tick_clock.cc",
- "time/tick_clock.h",
- "time/time.cc",
- "time/time.h",
- "time/time_override.cc",
- "time/time_override.h",
- "time/time_to_iso8601.cc",
- "time/time_to_iso8601.h",
- "timer/elapsed_timer.cc",
- "timer/elapsed_timer.h",
- "timer/hi_res_timer_manager.h",
- "timer/hi_res_timer_manager_win.cc",
- "timer/mock_timer.cc",
- "timer/mock_timer.h",
- "timer/timer.cc",
- "timer/timer.h",
- "trace_event/auto_open_close_event.cc",
- "trace_event/auto_open_close_event.h",
- "trace_event/blame_context.cc",
- "trace_event/blame_context.h",
- "trace_event/category_registry.cc",
- "trace_event/category_registry.h",
- "trace_event/common/trace_event_common.h",
- "trace_event/event_name_filter.cc",
- "trace_event/event_name_filter.h",
- "trace_event/heap_profiler.h",
- "trace_event/heap_profiler_allocation_context.cc",
- "trace_event/heap_profiler_allocation_context.h",
- "trace_event/heap_profiler_allocation_context_tracker.cc",
- "trace_event/heap_profiler_allocation_context_tracker.h",
- "trace_event/heap_profiler_event_filter.cc",
- "trace_event/heap_profiler_event_filter.h",
- "trace_event/heap_profiler_heap_dump_writer.cc",
- "trace_event/heap_profiler_heap_dump_writer.h",
- "trace_event/heap_profiler_serialization_state.cc",
- "trace_event/heap_profiler_serialization_state.h",
- "trace_event/heap_profiler_stack_frame_deduplicator.cc",
- "trace_event/heap_profiler_stack_frame_deduplicator.h",
- "trace_event/heap_profiler_type_name_deduplicator.cc",
- "trace_event/heap_profiler_type_name_deduplicator.h",
- "trace_event/java_heap_dump_provider_android.cc",
- "trace_event/java_heap_dump_provider_android.h",
- "trace_event/malloc_dump_provider.cc",
- "trace_event/malloc_dump_provider.h",
- "trace_event/memory_allocator_dump.cc",
- "trace_event/memory_allocator_dump.h",
- "trace_event/memory_allocator_dump_guid.cc",
- "trace_event/memory_allocator_dump_guid.h",
- "trace_event/memory_dump_manager.cc",
- "trace_event/memory_dump_manager.h",
- "trace_event/memory_dump_manager_test_utils.h",
- "trace_event/memory_dump_provider.h",
- "trace_event/memory_dump_provider_info.cc",
- "trace_event/memory_dump_provider_info.h",
- "trace_event/memory_dump_request_args.cc",
- "trace_event/memory_dump_request_args.h",
- "trace_event/memory_dump_scheduler.cc",
- "trace_event/memory_dump_scheduler.h",
- "trace_event/memory_infra_background_whitelist.cc",
- "trace_event/memory_infra_background_whitelist.h",
- "trace_event/memory_peak_detector.cc",
- "trace_event/memory_peak_detector.h",
- "trace_event/memory_usage_estimator.cc",
- "trace_event/memory_usage_estimator.h",
- "trace_event/process_memory_dump.cc",
- "trace_event/process_memory_dump.h",
- "trace_event/trace_buffer.cc",
- "trace_event/trace_buffer.h",
- "trace_event/trace_category.h",
- "trace_event/trace_config.cc",
- "trace_event/trace_config.h",
- "trace_event/trace_config_category_filter.cc",
- "trace_event/trace_config_category_filter.h",
- "trace_event/trace_event.h",
- "trace_event/trace_event_android.cc",
- "trace_event/trace_event_argument.cc",
- "trace_event/trace_event_argument.h",
- "trace_event/trace_event_etw_export_win.cc",
- "trace_event/trace_event_etw_export_win.h",
- "trace_event/trace_event_filter.cc",
- "trace_event/trace_event_filter.h",
- "trace_event/trace_event_impl.cc",
- "trace_event/trace_event_impl.h",
- "trace_event/trace_event_memory_overhead.cc",
- "trace_event/trace_event_memory_overhead.h",
- "trace_event/trace_event_system_stats_monitor.cc",
- "trace_event/trace_event_system_stats_monitor.h",
- "trace_event/trace_log.cc",
- "trace_event/trace_log.h",
- "trace_event/trace_log_constants.cc",
- "trace_event/tracing_agent.cc",
- "trace_event/tracing_agent.h",
- "tuple.h",
- "unguessable_token.cc",
- "unguessable_token.h",
- "value_conversions.cc",
- "value_conversions.h",
- "value_iterators.cc",
- "value_iterators.h",
- "values.cc",
- "values.h",
- "version.cc",
- "version.h",
- "vlog.cc",
- "vlog.h",
- "win/async_operation.h",
- "win/com_init_check_hook.cc",
- "win/com_init_check_hook.h",
- "win/com_init_util.cc",
- "win/com_init_util.h",
- "win/core_winrt_util.cc",
- "win/core_winrt_util.h",
- "win/current_module.h",
- "win/enum_variant.cc",
- "win/enum_variant.h",
- "win/event_trace_consumer.h",
- "win/event_trace_controller.cc",
- "win/event_trace_controller.h",
- "win/event_trace_provider.cc",
- "win/event_trace_provider.h",
- "win/i18n.cc",
- "win/i18n.h",
- "win/iat_patch_function.cc",
- "win/iat_patch_function.h",
- "win/iunknown_impl.cc",
- "win/iunknown_impl.h",
- "win/message_window.cc",
- "win/message_window.h",
- "win/object_watcher.cc",
- "win/object_watcher.h",
- "win/patch_util.cc",
- "win/patch_util.h",
- "win/process_startup_helper.cc",
- "win/process_startup_helper.h",
- "win/registry.cc",
- "win/registry.h",
- "win/resource_util.cc",
- "win/resource_util.h",
- "win/scoped_bstr.cc",
- "win/scoped_bstr.h",
- "win/scoped_co_mem.h",
- "win/scoped_com_initializer.cc",
- "win/scoped_com_initializer.h",
- "win/scoped_gdi_object.h",
- "win/scoped_handle.cc",
- "win/scoped_handle.h",
- "win/scoped_handle_verifier.cc",
- "win/scoped_handle_verifier.h",
- "win/scoped_hdc.h",
- "win/scoped_hglobal.h",
- "win/scoped_hstring.cc",
- "win/scoped_hstring.h",
- "win/scoped_process_information.cc",
- "win/scoped_process_information.h",
- "win/scoped_propvariant.h",
- "win/scoped_select_object.h",
- "win/scoped_variant.cc",
- "win/scoped_variant.h",
- "win/scoped_windows_thread_environment.h",
- "win/scoped_winrt_initializer.cc",
- "win/scoped_winrt_initializer.h",
- "win/shortcut.cc",
- "win/shortcut.h",
- "win/startup_information.cc",
- "win/startup_information.h",
- "win/typed_event_handler.h",
- "win/wait_chain.cc",
- "win/wait_chain.h",
- "win/win_util.cc",
- "win/win_util.h",
- "win/windows_version.cc",
- "win/windows_version.h",
- "win/winrt_storage_util.cc",
- "win/winrt_storage_util.h",
- "win/wrapped_window_proc.cc",
- "win/wrapped_window_proc.h",
- ]
-
- # winternl.h and NTSecAPI.h have different definitions of UNICODE_STRING.
- # There's only one client of NTSecAPI.h in base but several of winternl.h,
- # so exclude the NTSecAPI.h one.
- if (is_win) {
- jumbo_excluded_sources = [ "rand_util_win.cc" ]
- }
-
- if (is_posix) {
- sources += [
- "base_paths_posix.h",
- "debug/debugger_posix.cc",
- "debug/stack_trace_posix.cc",
- "file_descriptor_posix.h",
- "files/dir_reader_posix.h",
- "files/file_descriptor_watcher_posix.cc",
- "files/file_descriptor_watcher_posix.h",
- "files/file_enumerator_posix.cc",
- "files/file_posix.cc",
- "files/file_util_posix.cc",
- "files/memory_mapped_file_posix.cc",
- "memory/protected_memory_posix.cc",
- "message_loop/watchable_io_message_pump_posix.cc",
- "message_loop/watchable_io_message_pump_posix.h",
- "native_library_posix.cc",
- "posix/eintr_wrapper.h",
- "posix/file_descriptor_shuffle.cc",
- "posix/file_descriptor_shuffle.h",
- "posix/global_descriptors.cc",
- "posix/global_descriptors.h",
- "posix/safe_strerror.cc",
- "posix/safe_strerror.h",
- "posix/unix_domain_socket.cc",
- "posix/unix_domain_socket.h",
- "process/kill_posix.cc",
- "process/launch_posix.cc",
- "process/process_handle_posix.cc",
- "process/process_metrics_posix.cc",
- "process/process_posix.cc",
- "profiler/native_stack_sampler_posix.cc",
- "rand_util_posix.cc",
- "strings/string_util_posix.h",
- "strings/sys_string_conversions_posix.cc",
- "sync_socket_posix.cc",
- "synchronization/condition_variable_posix.cc",
- "synchronization/lock_impl_posix.cc",
- "synchronization/waitable_event_posix.cc",
- "synchronization/waitable_event_watcher_posix.cc",
- "sys_info_posix.cc",
- "task_scheduler/task_tracker_posix.cc",
- "task_scheduler/task_tracker_posix.h",
- "threading/platform_thread_internal_posix.cc",
- "threading/platform_thread_internal_posix.h",
- "threading/platform_thread_posix.cc",
- "threading/thread_local_storage_posix.cc",
- "timer/hi_res_timer_manager_posix.cc",
- ]
- }
-
- if (!is_nacl) {
- sources += [
- "base_paths.cc",
- "base_paths.h",
- "base_paths_android.cc",
- "base_paths_android.h",
- "base_paths_mac.h",
- "base_paths_mac.mm",
- "base_paths_posix.h",
- "base_paths_win.cc",
- "base_paths_win.h",
- "metrics/persistent_histogram_storage.cc",
- "metrics/persistent_histogram_storage.h",
- ]
-
- if (is_linux) {
- sources += [
- "base_paths_posix.cc",
- "debug/elf_reader_linux.cc",
- "debug/elf_reader_linux.h",
- ]
- }
- }
-
- all_dependent_configs = []
- defines = []
- data = []
- data_deps = []
-
- configs += [
- ":base_flags",
- ":base_implementation",
- "//build/config:precompiled_headers",
- "//build/config/compiler:noshadowing",
- ]
-
- deps = [
- "//base/allocator",
- "//base/allocator:buildflags",
- "//base/third_party/dynamic_annotations",
- "//third_party/modp_b64",
- ]
-
- public_deps = [
- ":anchor_functions_buildflags",
- ":base_static",
- ":build_date",
- ":cfi_buildflags",
- ":debugging_buildflags",
- ":partition_alloc_buildflags",
- ":protected_memory_buildflags",
- ":synchronization_buildflags",
- "//base/numerics:base_numerics",
- ]
-
- # Needed for <atomic> if using newer C++ library than sysroot, except if
- # building inside the cros_sdk environment - use host_toolchain as a
- # more robust check for this.
- if (!use_sysroot && (is_android || (is_linux && !is_chromecast)) &&
- host_toolchain != "//build/toolchain/cros:host") {
- libs = [ "atomic" ]
- }
-
- if (use_allocator_shim) {
- sources += [
- "allocator/allocator_shim.cc",
- "allocator/allocator_shim.h",
- "allocator/allocator_shim_internals.h",
- "allocator/allocator_shim_override_cpp_symbols.h",
- "allocator/allocator_shim_override_libc_symbols.h",
- ]
- if (is_win) {
- sources += [
- "allocator/allocator_shim_default_dispatch_to_winheap.cc",
- "allocator/allocator_shim_override_ucrt_symbols_win.h",
- "allocator/winheap_stubs_win.cc",
- "allocator/winheap_stubs_win.h",
- ]
- } else if (is_linux && use_allocator == "tcmalloc") {
- sources += [
- "allocator/allocator_shim_default_dispatch_to_tcmalloc.cc",
- "allocator/allocator_shim_override_glibc_weak_symbols.h",
- ]
- deps += [ "//base/allocator:tcmalloc" ]
- } else if (is_linux && use_allocator == "none") {
- sources += [ "allocator/allocator_shim_default_dispatch_to_glibc.cc" ]
- } else if (is_android && use_allocator == "none") {
- sources += [
- "allocator/allocator_shim_default_dispatch_to_linker_wrapped_symbols.cc",
- "allocator/allocator_shim_override_linker_wrapped_symbols.h",
- ]
- all_dependent_configs += [ "//base/allocator:wrap_malloc_symbols" ]
- } else if (is_mac) {
- sources += [
- "allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.cc",
- "allocator/allocator_shim_default_dispatch_to_mac_zoned_malloc.h",
- "allocator/allocator_shim_override_mac_symbols.h",
- ]
- }
- }
-
- # Allow more direct string conversions on platforms with native utf8
- # strings
- if (is_mac || is_ios || is_chromeos || is_chromecast || is_fuchsia) {
- defines += [ "SYSTEM_NATIVE_UTF8" ]
- }
-
- # Android.
- if (is_android) {
- sources -= [ "debug/stack_trace_posix.cc" ]
- sources += [
- "memory/platform_shared_memory_region_android.cc",
- "memory/shared_memory_android.cc",
- "memory/shared_memory_handle_android.cc",
- "time/time_android.cc",
- ]
-
- # Android uses some Linux sources, put those back.
- set_sources_assignment_filter([])
- sources += [
- "debug/elf_reader_linux.cc",
- "debug/elf_reader_linux.h",
- "debug/proc_maps_linux.cc",
- "debug/proc_maps_linux.h",
- "files/file_path_watcher_linux.cc",
- "power_monitor/power_monitor_device_source_android.cc",
- "process/internal_linux.cc",
- "process/internal_linux.h",
- "process/memory_linux.cc",
- "process/process_handle_linux.cc",
- "process/process_info_linux.cc",
- "process/process_iterator_linux.cc",
- "process/process_metrics_linux.cc",
- "sys_info_linux.cc",
- ]
- set_sources_assignment_filter(sources_assignment_filter)
-
- deps += [
- ":base_jni_headers",
- "//third_party/android_tools:cpu_features",
- "//third_party/ashmem",
- ]
-
- # TODO(thomasanderson): Remove this once use_custom_libcxx is always set to
- # true on Android.
- if (!use_custom_libcxx) {
- deps += [ "//buildtools/third_party/libc++abi:cxa_demangle_stub" ]
- }
-
- # Needs to be a public config so that dependent targets link against it as
- # well when doing a component build.
- public_configs = [ ":android_system_libs" ]
-
- if (can_unwind_with_cfi_table) {
- sources += [
- "trace_event/cfi_backtrace_android.cc",
- "trace_event/cfi_backtrace_android.h",
- ]
- }
-
- # This is actually a linker script, but it can be added to the link in the
- # same way as a library.
- libs = [ "android/library_loader/anchor_functions.lds" ]
- }
-
- # Chromeos.
- if (is_chromeos) {
- sources += [ "power_monitor/power_monitor_device_source_chromeos.cc" ]
- }
-
- # Fuchsia.
- if (is_fuchsia) {
- sources += [
- "base_paths_fuchsia.cc",
- "base_paths_fuchsia.h",
- "debug/debugger_posix.cc",
- "debug/stack_trace_fuchsia.cc",
- "file_descriptor_posix.h",
- "files/dir_reader_posix.h",
- "files/file_descriptor_watcher_posix.cc",
- "files/file_descriptor_watcher_posix.h",
- "files/file_enumerator_posix.cc",
- "files/file_path_watcher_fuchsia.cc",
- "files/file_posix.cc",
- "files/file_util_posix.cc",
- "files/memory_mapped_file_posix.cc",
- "fuchsia/async_dispatcher.cc",
- "fuchsia/async_dispatcher.h",
- "fuchsia/component_context.cc",
- "fuchsia/component_context.h",
- "fuchsia/default_job.cc",
- "fuchsia/default_job.h",
- "fuchsia/fidl_interface_request.cc",
- "fuchsia/fidl_interface_request.h",
- "fuchsia/fuchsia_logging.cc",
- "fuchsia/fuchsia_logging.h",
- "fuchsia/scoped_zx_handle.cc",
- "fuchsia/scoped_zx_handle.h",
- "fuchsia/services_directory.cc",
- "fuchsia/services_directory.h",
- "memory/platform_shared_memory_region_fuchsia.cc",
- "memory/protected_memory_posix.cc",
- "memory/shared_memory_fuchsia.cc",
- "memory/shared_memory_handle_fuchsia.cc",
- "message_loop/message_pump_fuchsia.cc",
- "message_loop/message_pump_fuchsia.h",
- "message_loop/watchable_io_message_pump_posix.cc",
- "message_loop/watchable_io_message_pump_posix.h",
- "native_library_fuchsia.cc",
- "posix/eintr_wrapper.h",
- "posix/file_descriptor_shuffle.cc",
- "posix/file_descriptor_shuffle.h",
- "posix/global_descriptors.cc",
- "posix/global_descriptors.h",
- "posix/safe_strerror.cc",
- "posix/safe_strerror.h",
- "process/kill_fuchsia.cc",
- "process/launch_fuchsia.cc",
- "process/memory_fuchsia.cc",
- "process/process_fuchsia.cc",
- "process/process_handle_fuchsia.cc",
- "process/process_iterator_fuchsia.cc",
- "process/process_metrics_fuchsia.cc",
- "process/process_metrics_posix.cc",
- "profiler/native_stack_sampler_posix.cc",
- "rand_util_fuchsia.cc",
- "strings/string_util_posix.h",
- "strings/sys_string_conversions_posix.cc",
- "sync_socket_posix.cc",
- "synchronization/condition_variable_posix.cc",
- "synchronization/lock_impl_posix.cc",
- "synchronization/waitable_event_posix.cc",
- "synchronization/waitable_event_watcher_posix.cc",
- "sys_info_fuchsia.cc",
- "sys_info_posix.cc",
- "task_scheduler/task_tracker_posix.cc",
- "task_scheduler/task_tracker_posix.h",
- "threading/platform_thread_fuchsia.cc",
- "threading/platform_thread_posix.cc",
- "threading/thread_local_storage_posix.cc",
- "time/time_conversion_posix.cc",
- "time/time_exploded_posix.cc",
- "time/time_fuchsia.cc",
- "timer/hi_res_timer_manager_posix.cc",
- ]
-
- # These only need to be public deps because of includes of their headers
- # by public //base headers, which requires they be on the include path.
- # TODO(https://crbug.com/841171): Move these back to |deps|.
- public_deps += [
- "//third_party/fuchsia-sdk:async",
- "//third_party/fuchsia-sdk:launchpad",
- ]
-
- deps += [
- "//third_party/fuchsia-sdk:async_default",
- "//third_party/fuchsia-sdk:fdio",
- "//third_party/fuchsia-sdk:fidl",
- "//third_party/fuchsia-sdk:svc",
- "//third_party/fuchsia-sdk:zx",
- ]
- }
-
- # NaCl.
- if (is_nacl) {
- # We reset sources_assignment_filter in order to explicitly include
- # the linux file (which would otherwise be filtered out).
- set_sources_assignment_filter([])
- sources += [
- "files/file_path_watcher_stub.cc",
- "memory/shared_memory_nacl.cc",
- "process/process_metrics_nacl.cc",
- "sync_socket_nacl.cc",
- "threading/platform_thread_linux.cc",
- ]
- set_sources_assignment_filter(sources_assignment_filter)
-
- sources -= [
- "cpu.cc",
- "debug/crash_logging.cc",
- "debug/crash_logging.h",
- "debug/stack_trace.cc",
- "debug/stack_trace_posix.cc",
- "files/file_enumerator_posix.cc",
- "files/file_proxy.cc",
- "files/important_file_writer.cc",
- "files/important_file_writer.h",
- "files/scoped_temp_dir.cc",
- "memory/discardable_memory.cc",
- "memory/discardable_memory.h",
- "memory/discardable_memory_allocator.cc",
- "memory/discardable_memory_allocator.h",
- "memory/discardable_shared_memory.cc",
- "memory/discardable_shared_memory.h",
- "memory/shared_memory_helper.cc",
- "memory/shared_memory_helper.h",
- "native_library.cc",
- "native_library_posix.cc",
- "path_service.cc",
- "process/kill.cc",
- "process/kill.h",
- "process/memory.cc",
- "process/memory.h",
- "process/process_iterator.cc",
- "process/process_iterator.h",
- "process/process_metrics.cc",
- "process/process_metrics_posix.cc",
- "process/process_posix.cc",
- "scoped_native_library.cc",
- "sync_socket_posix.cc",
- "sys_info.cc",
- "sys_info_posix.cc",
- "task_scheduler/initialization_util.cc",
- "task_scheduler/initialization_util.h",
- "trace_event/trace_event_system_stats_monitor.cc",
- ]
-
- if (is_nacl_nonsfi) {
- sources -= [ "rand_util_nacl.cc" ]
- configs += [ ":nacl_nonsfi_warnings" ]
- } else {
- sources -= [
- "files/file_descriptor_watcher_posix.cc",
- "files/file_descriptor_watcher_posix.h",
- "files/file_util.cc",
- "files/file_util.h",
- "files/file_util_posix.cc",
- "json/json_file_value_serializer.cc",
- "json/json_file_value_serializer.h",
- "posix/unix_domain_socket.cc",
- "process/kill_posix.cc",
- "process/launch.cc",
- "process/launch.h",
- "process/launch_posix.cc",
- "rand_util_posix.cc",
- "task_scheduler/task_tracker_posix.cc",
- "task_scheduler/task_tracker_posix.h",
- ]
- }
- } else {
- # Remove NaCl stuff.
- sources -= [
- "os_compat_nacl.cc",
- "os_compat_nacl.h",
- "rand_util_nacl.cc",
- ]
-
- if (use_partition_alloc) {
- # Add stuff that doesn't work in NaCl.
- sources += [
- # PartitionAlloc uses SpinLock, which doesn't work in NaCl (see below).
- "allocator/partition_allocator/address_space_randomization.cc",
- "allocator/partition_allocator/address_space_randomization.h",
- "allocator/partition_allocator/oom.h",
- "allocator/partition_allocator/page_allocator.cc",
- "allocator/partition_allocator/page_allocator.h",
- "allocator/partition_allocator/page_allocator_internal.h",
- "allocator/partition_allocator/partition_alloc.cc",
- "allocator/partition_allocator/partition_alloc.h",
- "allocator/partition_allocator/partition_alloc_constants.h",
- "allocator/partition_allocator/partition_bucket.cc",
- "allocator/partition_allocator/partition_bucket.h",
- "allocator/partition_allocator/partition_cookie.h",
- "allocator/partition_allocator/partition_direct_map_extent.h",
- "allocator/partition_allocator/partition_freelist_entry.h",
- "allocator/partition_allocator/partition_oom.cc",
- "allocator/partition_allocator/partition_oom.h",
- "allocator/partition_allocator/partition_page.cc",
- "allocator/partition_allocator/partition_page.h",
- "allocator/partition_allocator/partition_root_base.cc",
- "allocator/partition_allocator/partition_root_base.h",
- "allocator/partition_allocator/spin_lock.cc",
- "allocator/partition_allocator/spin_lock.h",
- ]
- if (is_win) {
- sources +=
- [ "allocator/partition_allocator/page_allocator_internals_win.h" ]
- } else if (is_posix || is_fuchsia) {
- sources +=
- [ "allocator/partition_allocator/page_allocator_internals_posix.h" ]
- }
- }
- }
-
- # Windows.
- if (is_win) {
- sources += [
- "memory/platform_shared_memory_region_win.cc",
- "memory/shared_memory_handle_win.cc",
- "memory/shared_memory_win.cc",
- "power_monitor/power_monitor_device_source_win.cc",
- "profiler/win32_stack_frame_unwinder.cc",
- "profiler/win32_stack_frame_unwinder.h",
- "time/time_win.cc",
- ]
-
- sources -= [
- "file_descriptor_store.cc",
- "file_descriptor_store.h",
- "memory/shared_memory_helper.cc",
- "memory/shared_memory_helper.h",
- "strings/string16.cc",
- ]
-
- deps += [
- "//base/trace_event/etw_manifest:chrome_events_win",
- "//base/win:base_win_buildflags",
- ]
-
- data_deps += [ "//build/win:runtime_libs" ]
-
- if (com_init_check_hook_disabled) {
- defines += [ "COM_INIT_CHECK_HOOK_DISABLED" ]
- }
-
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
- libs = [
- "cfgmgr32.lib",
- "powrprof.lib",
- "propsys.lib",
- "setupapi.lib",
- "userenv.lib",
- "winmm.lib",
- ]
- all_dependent_configs += [
- ":base_win_linker_flags",
- "//tools/win/DebugVisualizers:chrome",
- ]
- }
-
- # Desktop Mac.
- if (is_mac) {
- sources -= [ "profiler/native_stack_sampler_posix.cc" ]
- sources += [
- "mac/scoped_typeref.h",
- "memory/platform_shared_memory_region_mac.cc",
- "memory/shared_memory_handle_mac.cc",
- "memory/shared_memory_mac.cc",
- "power_monitor/power_monitor_device_source_mac.mm",
- "time/time_conversion_posix.cc",
- "time/time_exploded_posix.cc",
- "time/time_mac.cc",
- ]
-
- libs = [
- "ApplicationServices.framework",
- "AppKit.framework",
- "bsm",
- "CoreFoundation.framework",
- "IOKit.framework",
- "Security.framework",
- ]
- }
-
- # Mac or iOS.
- if (is_mac || is_ios) {
- sources -= [
- "native_library_posix.cc",
- "strings/sys_string_conversions_posix.cc",
- "synchronization/waitable_event_posix.cc",
- "synchronization/waitable_event_watcher_posix.cc",
- "threading/platform_thread_internal_posix.cc",
- ]
- } else {
- # Non-Mac/ios.
- sources -= [
- "files/file_path_watcher_fsevents.cc",
- "files/file_path_watcher_fsevents.h",
- "files/file_path_watcher_kqueue.cc",
- "files/file_path_watcher_kqueue.h",
- ]
- }
-
- # Linux.
- if (is_linux) {
- # TODO(brettw) this will need to be parameterized at some point.
- linux_configs = []
- if (use_glib) {
- linux_configs += [ "//build/config/linux:glib" ]
- }
-
- defines += [ "USE_SYMBOLIZE" ]
-
- configs += linux_configs
- all_dependent_configs += linux_configs
-
- # These dependencies are not required on Android, and in the case
- # of xdg_mime must be excluded due to licensing restrictions.
- deps += [
- "//base/third_party/symbolize",
- "//base/third_party/xdg_mime",
- "//base/third_party/xdg_user_dirs",
- ]
- } else {
- # Non-Linux.
- sources -= [
- "nix/mime_util_xdg.cc",
- "nix/mime_util_xdg.h",
- "nix/xdg_util.cc",
- "nix/xdg_util.h",
- ]
-
- if (!is_android) {
- sources -= [
- "linux_util.cc",
- "linux_util.h",
- ]
- }
- }
-
- # iOS
- if (is_ios) {
- set_sources_assignment_filter([])
-
- sources -= [
- "files/file_path_watcher.cc",
- "files/file_path_watcher.h",
- "files/file_path_watcher_fsevents.cc",
- "files/file_path_watcher_fsevents.h",
- "files/file_path_watcher_kqueue.cc",
- "files/file_path_watcher_kqueue.h",
- "memory/discardable_shared_memory.cc",
- "memory/discardable_shared_memory.h",
- "process/kill.cc",
- "process/kill.h",
- "process/kill_posix.cc",
- "process/launch.cc",
- "process/launch.h",
- "process/launch_posix.cc",
- "process/memory.cc",
- "process/memory.h",
- "process/process_iterator.cc",
- "process/process_iterator.h",
- "process/process_metrics_posix.cc",
- "process/process_posix.cc",
- "sync_socket.h",
- "sync_socket_posix.cc",
- "synchronization/waitable_event_watcher.h",
- ]
- sources += [
- "base_paths_mac.h",
- "base_paths_mac.mm",
- "file_version_info_mac.h",
- "file_version_info_mac.mm",
- "files/file_util_mac.mm",
- "mac/bundle_locations.h",
- "mac/bundle_locations.mm",
- "mac/call_with_eh_frame.cc",
- "mac/call_with_eh_frame.h",
- "mac/foundation_util.h",
- "mac/foundation_util.mm",
- "mac/mac_logging.h",
- "mac/mac_logging.mm",
- "mac/mach_logging.cc",
- "mac/mach_logging.h",
- "mac/objc_release_properties.h",
- "mac/objc_release_properties.mm",
- "mac/scoped_block.h",
- "mac/scoped_mach_port.cc",
- "mac/scoped_mach_port.h",
- "mac/scoped_mach_vm.cc",
- "mac/scoped_mach_vm.h",
- "mac/scoped_nsautorelease_pool.h",
- "mac/scoped_nsautorelease_pool.mm",
- "mac/scoped_nsobject.h",
- "mac/scoped_nsobject.mm",
- "mac/scoped_objc_class_swizzler.h",
- "mac/scoped_objc_class_swizzler.mm",
- "mac/scoped_typeref.h",
- "message_loop/message_pump_mac.h",
- "message_loop/message_pump_mac.mm",
- "power_monitor/power_monitor_device_source_ios.mm",
- "process/memory_stubs.cc",
- "strings/sys_string_conversions_mac.mm",
- "synchronization/waitable_event_mac.cc",
- "threading/platform_thread_mac.mm",
- "time/time_conversion_posix.cc",
- "time/time_mac.cc",
- ]
-
- set_sources_assignment_filter(sources_assignment_filter)
- }
-
- if (dep_libevent) {
- deps += [ "//base/third_party/libevent" ]
- }
-
- if (use_libevent) {
- sources += [
- "message_loop/message_pump_libevent.cc",
- "message_loop/message_pump_libevent.h",
- ]
- }
-
- # Android and MacOS have their own custom shared memory handle
- # implementations. e.g. due to supporting both POSIX and native handles.
- if (is_posix && !is_android && !is_mac) {
- sources += [
- "memory/platform_shared_memory_region_posix.cc",
- "memory/shared_memory_handle_posix.cc",
- ]
- }
-
- if (is_posix && !is_mac && !is_nacl) {
- sources += [ "memory/shared_memory_posix.cc" ]
- }
-
- if (is_posix && !is_mac && !is_ios) {
- sources += [
- "time/time_conversion_posix.cc",
- "time/time_exploded_posix.cc",
- "time/time_now_posix.cc",
- ]
- }
-
- if ((is_posix && !is_mac && !is_ios && !is_android && !is_chromeos) ||
- is_fuchsia) {
- sources += [ "power_monitor/power_monitor_device_source_stub.cc" ]
- }
-
- if (!use_glib) {
- sources -= [
- "message_loop/message_pump_glib.cc",
- "message_loop/message_pump_glib.h",
- ]
- }
-
- if (using_sanitizer) {
- data += [ "//tools/valgrind/asan/" ]
- if (is_win) {
- data +=
- [ "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer.exe" ]
- } else {
- data += [ "//third_party/llvm-build/Release+Asserts/bin/llvm-symbolizer" ]
- }
- }
-
- configs += [ "//build/config/compiler:wexit_time_destructors" ]
- if (!is_debug) {
- configs -= [ "//build/config/compiler:default_optimization" ]
- configs += [ "//build/config/compiler:optimize_max" ]
- }
-}
-
-# Build flags for Control Flow Integrity
-# https://www.chromium.org/developers/testing/control-flow-integrity
-buildflag_header("cfi_buildflags") {
- header = "cfi_buildflags.h"
-
- # buildflag entries added to this header must also must be manually added to
- # tools/gn/bootstrap/bootstrap.py
- flags = [
- # TODO(pcc): remove CFI_CAST_CHECK, see https://crbug.com/626794.
- "CFI_CAST_CHECK=$is_cfi && $use_cfi_cast",
- "CFI_ICALL_CHECK=$is_cfi && $use_cfi_icall",
- "CFI_ENFORCEMENT_TRAP=$is_cfi && !$use_cfi_diag",
- "CFI_ENFORCEMENT_DIAGNOSTIC=$is_cfi && $use_cfi_diag && !$use_cfi_recover",
- ]
-}
-
-buildflag_header("debugging_buildflags") {
- header = "debugging_buildflags.h"
- header_dir = "base/debug"
-
- # buildflag entries added to this header must also must be manually added to
- # tools/gn/bootstrap/bootstrap.py
- flags = [
- "ENABLE_LOCATION_SOURCE=$enable_location_source",
- "ENABLE_PROFILING=$enable_profiling",
- "CAN_UNWIND_WITH_FRAME_POINTERS=$can_unwind_with_frame_pointers",
- "UNSAFE_DEVELOPER_BUILD=$is_unsafe_developer_build",
- "CAN_UNWIND_WITH_CFI_TABLE=$can_unwind_with_cfi_table",
- ]
-}
-
-# Build flags for ProtectedMemory, temporary workaround for crbug.com/792777
-# TODO(vtsyrklevich): Remove once support for gold on Android/CrOs is dropped
-buildflag_header("protected_memory_buildflags") {
- header = "protected_memory_buildflags.h"
- header_dir = "base/memory"
-
- # buildflag entries added to this header must also must be manually added to
- # tools/gn/bootstrap/bootstrap.py
- flags = [ "USE_LLD=$use_lld" ]
-}
-
-buildflag_header("synchronization_buildflags") {
- header = "synchronization_buildflags.h"
- header_dir = "base/synchronization"
-
- flags =
- [ "ENABLE_MUTEX_PRIORITY_INHERITANCE=$enable_mutex_priority_inheritance" ]
-}
-
-buildflag_header("anchor_functions_buildflags") {
- header = "anchor_functions_buildflags.h"
- header_dir = "base/android/library_loader"
- _supports_code_ordering = current_cpu == "arm"
-
- # buildflag entries added to this header must also must be manually added to
- # tools/gn/bootstrap/bootstrap.py
- flags = [
- "USE_LLD=$use_lld",
- "SUPPORTS_CODE_ORDERING=$_supports_code_ordering",
- ]
-}
-
-buildflag_header("partition_alloc_buildflags") {
- header = "partition_alloc_buildflags.h"
- header_dir = "base"
-
- flags = [ "USE_PARTITION_ALLOC=$use_partition_alloc" ]
-}
-
-# This is the subset of files from base that should not be used with a dynamic
-# library. Note that this library cannot depend on base because base depends on
-# base_static.
-static_library("base_static") {
- sources = [
- "base_switches.cc",
- "base_switches.h",
- ]
-
- if (is_win) {
- public_deps = [
- "//base/win:pe_image",
- ]
-
- # Disable sanitizer coverage in win/pe_image.cc. It is called by the sandbox
- # before sanitizer coverage can initialize. http://crbug.com/484711
- configs -= [ "//build/config/sanitizers:default_sanitizer_flags" ]
- configs +=
- [ "//build/config/sanitizers:default_sanitizer_flags_but_coverage" ]
- }
-
- if (!is_debug) {
- configs -= [ "//build/config/compiler:default_optimization" ]
- configs += [ "//build/config/compiler:optimize_max" ]
- }
-}
-
-component("i18n") {
- output_name = "base_i18n"
- sources = [
- "i18n/base_i18n_export.h",
- "i18n/base_i18n_switches.cc",
- "i18n/base_i18n_switches.h",
- "i18n/bidi_line_iterator.cc",
- "i18n/bidi_line_iterator.h",
- "i18n/break_iterator.cc",
- "i18n/break_iterator.h",
- "i18n/case_conversion.cc",
- "i18n/case_conversion.h",
- "i18n/char_iterator.cc",
- "i18n/char_iterator.h",
- "i18n/character_encoding.cc",
- "i18n/character_encoding.h",
- "i18n/encoding_detection.cc",
- "i18n/encoding_detection.h",
- "i18n/file_util_icu.cc",
- "i18n/file_util_icu.h",
- "i18n/i18n_constants.cc",
- "i18n/i18n_constants.h",
- "i18n/icu_string_conversions.cc",
- "i18n/icu_string_conversions.h",
- "i18n/icu_util.cc",
- "i18n/icu_util.h",
- "i18n/message_formatter.cc",
- "i18n/message_formatter.h",
- "i18n/number_formatting.cc",
- "i18n/number_formatting.h",
- "i18n/rtl.cc",
- "i18n/rtl.h",
- "i18n/streaming_utf8_validator.cc",
- "i18n/streaming_utf8_validator.h",
- "i18n/string_compare.cc",
- "i18n/string_compare.h",
- "i18n/string_search.cc",
- "i18n/string_search.h",
- "i18n/time_formatting.cc",
- "i18n/time_formatting.h",
- "i18n/timezone.cc",
- "i18n/timezone.h",
- "i18n/unicodestring.h",
- "i18n/utf8_validator_tables.cc",
- "i18n/utf8_validator_tables.h",
- ]
- defines = [ "BASE_I18N_IMPLEMENTATION" ]
- configs += [ "//build/config/compiler:wexit_time_destructors" ]
- public_deps = [
- "//third_party/ced",
- "//third_party/icu",
- ]
- deps = [
- ":base",
- "//base/third_party/dynamic_annotations",
- ]
-
- if (!is_debug) {
- configs -= [ "//build/config/compiler:default_optimization" ]
- configs += [ "//build/config/compiler:optimize_max" ]
- }
-
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
- if (is_mac) {
- libs = [ "CoreFoundation.framework" ]
- }
-}
-
-test("base_perftests") {
- sources = [
- "message_loop/message_loop_perftest.cc",
- "message_loop/message_pump_perftest.cc",
-
- # "test/run_all_unittests.cc",
- "json/json_perftest.cc",
- "synchronization/waitable_event_perftest.cc",
- "threading/thread_perftest.cc",
- ]
- deps = [
- ":base",
- "//base/test:test_support",
- "//base/test:test_support_perf",
- "//testing/gtest",
- "//testing/perf",
- ]
-
- if (is_android) {
- deps += [ "//testing/android/native_test:native_test_native_code" ]
- }
-}
-
-test("base_i18n_perftests") {
- sources = [
- "i18n/streaming_utf8_validator_perftest.cc",
- ]
- deps = [
- ":base",
- ":i18n",
- "//base/test:test_support",
- "//base/test:test_support_perf",
- "//testing/gtest",
- ]
-}
-
-if (!is_ios) {
- executable("build_utf8_validator_tables") {
- sources = [
- "i18n/build_utf8_validator_tables.cc",
- ]
- deps = [
- ":base",
- "//build/config:exe_and_shlib_deps",
- "//build/win:default_exe_manifest",
- "//third_party/icu:icuuc",
- ]
- }
-
- executable("check_example") {
- sources = [
- "check_example.cc",
- ]
- deps = [
- ":base",
- "//build/config:exe_and_shlib_deps",
- "//build/win:default_exe_manifest",
- ]
- }
-}
-
-if (is_win) {
- # Target to manually rebuild pe_image_test.dll which is checked into
- # base/test/data/pe_image.
- shared_library("pe_image_test") {
- sources = [
- "win/pe_image_test.cc",
- ]
- ldflags = [
- "/DELAYLOAD:cfgmgr32.dll",
- "/DELAYLOAD:shell32.dll",
- "/SUBSYSTEM:WINDOWS",
- ]
- libs = [
- "cfgmgr32.lib",
- "shell32.lib",
- ]
- deps = [
- "//build/config:exe_and_shlib_deps",
- ]
- }
-
- loadable_module("scoped_handle_test_dll") {
- sources = [
- "win/scoped_handle_test_dll.cc",
- ]
- deps = [
- ":base",
- "//base/win:base_win_buildflags",
- ]
- }
-}
-
-if (is_win || is_mac) {
- if (current_cpu == "x64") {
- # Must be a shared library so that it can be unloaded during testing.
- shared_library("base_profiler_test_support_library") {
- sources = [
- "profiler/test_support_library.cc",
- ]
- deps = [
- "//build/config:exe_and_shlib_deps",
- ]
- }
- }
-}
-
-bundle_data("base_unittests_bundle_data") {
- testonly = true
- sources = [
- "test/data/file_util/binary_file.bin",
- "test/data/file_util/binary_file_diff.bin",
- "test/data/file_util/binary_file_same.bin",
- "test/data/file_util/blank_line.txt",
- "test/data/file_util/blank_line_crlf.txt",
- "test/data/file_util/crlf.txt",
- "test/data/file_util/different.txt",
- "test/data/file_util/different_first.txt",
- "test/data/file_util/different_last.txt",
- "test/data/file_util/empty1.txt",
- "test/data/file_util/empty2.txt",
- "test/data/file_util/first1.txt",
- "test/data/file_util/first2.txt",
- "test/data/file_util/original.txt",
- "test/data/file_util/same.txt",
- "test/data/file_util/same_length.txt",
- "test/data/file_util/shortened.txt",
- "test/data/json/bom_feff.json",
- "test/data/serializer_nested_test.json",
- "test/data/serializer_test.json",
- "test/data/serializer_test_nowhitespace.json",
- ]
- outputs = [
- "{{bundle_resources_dir}}/" +
- "{{source_root_relative_dir}}/{{source_file_part}}",
- ]
-}
-
-if (is_ios || is_mac) {
- source_set("base_unittests_arc") {
- testonly = true
- set_sources_assignment_filter([])
- sources = [
- "mac/bind_objc_block_unittest_arc.mm",
- "mac/scoped_nsobject_unittest_arc.mm",
- ]
- set_sources_assignment_filter(sources_assignment_filter)
- configs += [ "//build/config/compiler:enable_arc" ]
- deps = [
- ":base",
- "//testing/gtest",
- ]
- }
-}
-
-if (is_fuchsia) {
- fidl_library("test_fidl") {
- namespace = "base.fuchsia"
- namespace_path = "base/fuchsia"
-
- sources = [
- "fuchsia/test.fidl",
- ]
- }
-}
-
-test("base_unittests") {
- sources = [
- "allocator/allocator_interception_mac_unittest.mm",
- "allocator/malloc_zone_functions_mac_unittest.cc",
- "allocator/tcmalloc_unittest.cc",
- "android/application_status_listener_unittest.cc",
- "android/content_uri_utils_unittest.cc",
- "android/jni_android_unittest.cc",
- "android/jni_array_unittest.cc",
- "android/jni_string_unittest.cc",
- "android/library_loader/library_prefetcher_unittest.cc",
- "android/path_utils_unittest.cc",
- "android/scoped_java_ref_unittest.cc",
- "android/sys_utils_unittest.cc",
- "android/unguessable_token_android_unittest.cc",
- "at_exit_unittest.cc",
- "atomicops_unittest.cc",
- "barrier_closure_unittest.cc",
- "base64_unittest.cc",
- "base64url_unittest.cc",
- "big_endian_unittest.cc",
- "bind_unittest.cc",
- "bit_cast_unittest.cc",
- "bits_unittest.cc",
- "build_time_unittest.cc",
- "callback_helpers_unittest.cc",
- "callback_list_unittest.cc",
- "callback_unittest.cc",
- "cancelable_callback_unittest.cc",
- "command_line_unittest.cc",
- "component_export_unittest.cc",
- "containers/adapters_unittest.cc",
- "containers/circular_deque_unittest.cc",
- "containers/flat_map_unittest.cc",
- "containers/flat_set_unittest.cc",
- "containers/flat_tree_unittest.cc",
- "containers/hash_tables_unittest.cc",
- "containers/id_map_unittest.cc",
- "containers/linked_list_unittest.cc",
- "containers/mru_cache_unittest.cc",
- "containers/small_map_unittest.cc",
- "containers/span_unittest.cc",
- "containers/stack_container_unittest.cc",
- "containers/unique_ptr_adapters_unittest.cc",
- "containers/vector_buffer_unittest.cc",
- "cpu_unittest.cc",
- "debug/activity_analyzer_unittest.cc",
- "debug/activity_tracker_unittest.cc",
- "debug/alias_unittest.cc",
- "debug/crash_logging_unittest.cc",
- "debug/debugger_unittest.cc",
- "debug/elf_reader_linux_unittest.cc",
- "debug/leak_tracker_unittest.cc",
- "debug/proc_maps_linux_unittest.cc",
- "debug/stack_trace_unittest.cc",
- "debug/task_annotator_unittest.cc",
- "debug/thread_heap_usage_tracker_unittest.cc",
- "deferred_sequenced_task_runner_unittest.cc",
- "environment_unittest.cc",
- "feature_list_unittest.cc",
- "file_version_info_win_unittest.cc",
- "files/file_enumerator_unittest.cc",
- "files/file_path_unittest.cc",
- "files/file_path_watcher_unittest.cc",
- "files/file_proxy_unittest.cc",
- "files/file_unittest.cc",
- "files/file_util_unittest.cc",
- "files/important_file_writer_unittest.cc",
- "files/memory_mapped_file_unittest.cc",
- "files/scoped_temp_dir_unittest.cc",
- "gmock_unittest.cc",
- "guid_unittest.cc",
- "hash_unittest.cc",
- "i18n/bidi_line_iterator_unittest.cc",
- "i18n/break_iterator_unittest.cc",
- "i18n/case_conversion_unittest.cc",
- "i18n/char_iterator_unittest.cc",
- "i18n/character_encoding_unittest.cc",
- "i18n/file_util_icu_unittest.cc",
- "i18n/icu_string_conversions_unittest.cc",
- "i18n/message_formatter_unittest.cc",
- "i18n/number_formatting_unittest.cc",
- "i18n/rtl_unittest.cc",
- "i18n/streaming_utf8_validator_unittest.cc",
- "i18n/string_search_unittest.cc",
- "i18n/time_formatting_unittest.cc",
- "i18n/timezone_unittest.cc",
- "ios/crb_protocol_observers_unittest.mm",
- "ios/device_util_unittest.mm",
- "ios/weak_nsobject_unittest.mm",
- "json/json_parser_unittest.cc",
- "json/json_reader_unittest.cc",
- "json/json_value_converter_unittest.cc",
- "json/json_value_serializer_unittest.cc",
- "json/json_writer_unittest.cc",
- "json/string_escape_unittest.cc",
- "lazy_instance_unittest.cc",
- "logging_unittest.cc",
- "mac/bind_objc_block_unittest.mm",
- "mac/call_with_eh_frame_unittest.mm",
- "mac/dispatch_source_mach_unittest.cc",
- "mac/foundation_util_unittest.mm",
- "mac/mac_util_unittest.mm",
- "mac/mach_port_broker_unittest.cc",
- "mac/objc_release_properties_unittest.mm",
- "mac/scoped_nsobject_unittest.mm",
- "mac/scoped_objc_class_swizzler_unittest.mm",
- "mac/scoped_sending_event_unittest.mm",
- "md5_unittest.cc",
- "memory/aligned_memory_unittest.cc",
- "memory/discardable_shared_memory_unittest.cc",
- "memory/linked_ptr_unittest.cc",
- "memory/memory_coordinator_client_registry_unittest.cc",
- "memory/memory_pressure_listener_unittest.cc",
- "memory/memory_pressure_monitor_chromeos_unittest.cc",
- "memory/memory_pressure_monitor_mac_unittest.cc",
- "memory/memory_pressure_monitor_unittest.cc",
- "memory/memory_pressure_monitor_win_unittest.cc",
- "memory/platform_shared_memory_region_unittest.cc",
- "memory/protected_memory_unittest.cc",
- "memory/ptr_util_unittest.cc",
- "memory/ref_counted_memory_unittest.cc",
- "memory/ref_counted_unittest.cc",
- "memory/shared_memory_mac_unittest.cc",
- "memory/shared_memory_region_unittest.cc",
- "memory/shared_memory_unittest.cc",
- "memory/shared_memory_win_unittest.cc",
- "memory/singleton_unittest.cc",
- "memory/weak_ptr_unittest.cc",
- "message_loop/message_loop_task_runner_unittest.cc",
- "message_loop/message_loop_unittest.cc",
- "message_loop/message_pump_glib_unittest.cc",
- "message_loop/message_pump_io_ios_unittest.cc",
- "message_loop/message_pump_mac_unittest.mm",
- "metrics/bucket_ranges_unittest.cc",
- "metrics/field_trial_params_unittest.cc",
- "metrics/field_trial_unittest.cc",
- "metrics/histogram_base_unittest.cc",
- "metrics/histogram_delta_serialization_unittest.cc",
- "metrics/histogram_functions_unittest.cc",
- "metrics/histogram_macros_unittest.cc",
- "metrics/histogram_samples_unittest.cc",
- "metrics/histogram_snapshot_manager_unittest.cc",
- "metrics/histogram_unittest.cc",
- "metrics/metrics_hashes_unittest.cc",
- "metrics/persistent_histogram_allocator_unittest.cc",
- "metrics/persistent_histogram_storage_unittest.cc",
- "metrics/persistent_memory_allocator_unittest.cc",
- "metrics/persistent_sample_map_unittest.cc",
- "metrics/sample_map_unittest.cc",
- "metrics/sample_vector_unittest.cc",
- "metrics/single_sample_metrics_unittest.cc",
- "metrics/sparse_histogram_unittest.cc",
- "metrics/statistics_recorder_unittest.cc",
- "native_library_unittest.cc",
- "no_destructor_unittest.cc",
- "observer_list_unittest.cc",
- "optional_unittest.cc",
- "os_compat_android_unittest.cc",
- "path_service_unittest.cc",
- "pickle_unittest.cc",
- "power_monitor/power_monitor_unittest.cc",
- "process/launch_unittest_win.cc",
- "process/memory_unittest.cc",
- "process/memory_unittest_mac.h",
- "process/memory_unittest_mac.mm",
- "process/process_info_unittest.cc",
- "process/process_metrics_unittest.cc",
- "process/process_unittest.cc",
- "process/process_util_unittest.cc",
- "profiler/stack_sampling_profiler_unittest.cc",
- "rand_util_unittest.cc",
- "run_loop_unittest.cc",
- "safe_numerics_unittest.cc",
- "scoped_clear_errno_unittest.cc",
- "scoped_generic_unittest.cc",
- "scoped_native_library_unittest.cc",
- "security_unittest.cc",
- "sequence_checker_unittest.cc",
- "sequence_token_unittest.cc",
- "sequenced_task_runner_unittest.cc",
- "sha1_unittest.cc",
- "stl_util_unittest.cc",
- "strings/char_traits_unittest.cc",
- "strings/nullable_string16_unittest.cc",
- "strings/pattern_unittest.cc",
- "strings/safe_sprintf_unittest.cc",
- "strings/strcat_unittest.cc",
- "strings/string16_unittest.cc",
- "strings/string_number_conversions_unittest.cc",
- "strings/string_piece_unittest.cc",
- "strings/string_split_unittest.cc",
- "strings/string_tokenizer_unittest.cc",
- "strings/string_util_unittest.cc",
- "strings/stringize_macros_unittest.cc",
- "strings/stringprintf_unittest.cc",
- "strings/sys_string_conversions_mac_unittest.mm",
- "strings/sys_string_conversions_unittest.cc",
- "strings/utf_offset_string_conversions_unittest.cc",
- "strings/utf_string_conversions_unittest.cc",
- "supports_user_data_unittest.cc",
- "sync_socket_unittest.cc",
- "synchronization/atomic_flag_unittest.cc",
- "synchronization/condition_variable_unittest.cc",
- "synchronization/lock_unittest.cc",
- "synchronization/waitable_event_unittest.cc",
- "synchronization/waitable_event_watcher_unittest.cc",
- "sys_byteorder_unittest.cc",
- "sys_info_unittest.cc",
- "system_monitor/system_monitor_unittest.cc",
- "task/cancelable_task_tracker_unittest.cc",
- "task_runner_util_unittest.cc",
- "task_scheduler/delayed_task_manager_unittest.cc",
- "task_scheduler/lazy_task_runner_unittest.cc",
- "task_scheduler/priority_queue_unittest.cc",
- "task_scheduler/scheduler_lock_unittest.cc",
- "task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc",
- "task_scheduler/scheduler_worker_pool_impl_unittest.cc",
- "task_scheduler/scheduler_worker_pool_unittest.cc",
- "task_scheduler/scheduler_worker_stack_unittest.cc",
- "task_scheduler/scheduler_worker_unittest.cc",
- "task_scheduler/scoped_set_task_priority_for_current_thread_unittest.cc",
- "task_scheduler/sequence_sort_key_unittest.cc",
- "task_scheduler/sequence_unittest.cc",
- "task_scheduler/service_thread_unittest.cc",
- "task_scheduler/task_scheduler_impl_unittest.cc",
- "task_scheduler/task_tracker_unittest.cc",
- "task_scheduler/task_traits_unittest.cc",
- "task_scheduler/task_unittest.cc",
- "task_scheduler/test_task_factory.cc",
- "task_scheduler/test_task_factory.h",
- "task_scheduler/test_utils.cc",
- "task_scheduler/test_utils.h",
- "task_scheduler/tracked_ref_unittest.cc",
- "template_util_unittest.cc",
- "test/histogram_tester_unittest.cc",
- "test/mock_callback_unittest.cc",
- "test/scoped_feature_list_unittest.cc",
- "test/scoped_mock_time_message_loop_task_runner_unittest.cc",
- "test/scoped_task_environment_unittest.cc",
- "test/test_mock_time_task_runner_unittest.cc",
- "test/test_pending_task_unittest.cc",
- "test/test_reg_util_win_unittest.cc",
- "test/trace_event_analyzer_unittest.cc",
- "test/user_action_tester_unittest.cc",
- "thread_annotations_unittest.cc",
- "threading/platform_thread_unittest.cc",
- "threading/post_task_and_reply_impl_unittest.cc",
- "threading/scoped_blocking_call_unittest.cc",
- "threading/sequence_local_storage_map_unittest.cc",
- "threading/sequence_local_storage_slot_unittest.cc",
- "threading/sequenced_task_runner_handle_unittest.cc",
- "threading/simple_thread_unittest.cc",
- "threading/thread_checker_unittest.cc",
- "threading/thread_collision_warner_unittest.cc",
- "threading/thread_id_name_manager_unittest.cc",
- "threading/thread_local_storage_unittest.cc",
- "threading/thread_local_unittest.cc",
- "threading/thread_restrictions_unittest.cc",
- "threading/thread_task_runner_handle_unittest.cc",
- "threading/thread_unittest.cc",
- "threading/watchdog_unittest.cc",
- "time/pr_time_unittest.cc",
- "time/time_unittest.cc",
- "time/time_win_unittest.cc",
- "timer/hi_res_timer_manager_unittest.cc",
- "timer/mock_timer_unittest.cc",
- "timer/timer_unittest.cc",
- "tools_sanity_unittest.cc",
- "trace_event/blame_context_unittest.cc",
- "trace_event/event_name_filter_unittest.cc",
- "trace_event/heap_profiler_allocation_context_tracker_unittest.cc",
- "trace_event/heap_profiler_heap_dump_writer_unittest.cc",
- "trace_event/heap_profiler_stack_frame_deduplicator_unittest.cc",
- "trace_event/heap_profiler_type_name_deduplicator_unittest.cc",
- "trace_event/java_heap_dump_provider_android_unittest.cc",
- "trace_event/memory_allocator_dump_unittest.cc",
- "trace_event/memory_dump_manager_unittest.cc",
- "trace_event/memory_dump_scheduler_unittest.cc",
- "trace_event/memory_peak_detector_unittest.cc",
- "trace_event/memory_usage_estimator_unittest.cc",
- "trace_event/process_memory_dump_unittest.cc",
- "trace_event/trace_category_unittest.cc",
- "trace_event/trace_config_unittest.cc",
- "trace_event/trace_event_argument_unittest.cc",
- "trace_event/trace_event_filter_test_utils.cc",
- "trace_event/trace_event_filter_test_utils.h",
- "trace_event/trace_event_system_stats_monitor_unittest.cc",
- "trace_event/trace_event_unittest.cc",
- "tuple_unittest.cc",
- "unguessable_token_unittest.cc",
- "value_iterators_unittest.cc",
- "values_unittest.cc",
- "version_unittest.cc",
- "vlog_unittest.cc",
- "win/async_operation_unittest.cc",
- "win/com_init_check_hook_unittest.cc",
- "win/com_init_util_unittest.cc",
- "win/core_winrt_util_unittest.cc",
- "win/dllmain.cc",
- "win/enum_variant_unittest.cc",
- "win/event_trace_consumer_unittest.cc",
- "win/event_trace_controller_unittest.cc",
- "win/event_trace_provider_unittest.cc",
- "win/i18n_unittest.cc",
- "win/iunknown_impl_unittest.cc",
- "win/message_window_unittest.cc",
- "win/object_watcher_unittest.cc",
- "win/pe_image_unittest.cc",
- "win/registry_unittest.cc",
- "win/scoped_bstr_unittest.cc",
- "win/scoped_handle_unittest.cc",
- "win/scoped_hstring_unittest.cc",
- "win/scoped_process_information_unittest.cc",
- "win/scoped_variant_unittest.cc",
- "win/scoped_winrt_initializer_unittest.cc",
- "win/shortcut_unittest.cc",
- "win/startup_information_unittest.cc",
- "win/typed_event_handler_unittest.cc",
- "win/wait_chain_unittest.cc",
- "win/win_includes_unittest.cc",
- "win/win_util_unittest.cc",
- "win/windows_version_unittest.cc",
- "win/winrt_storage_util_unittest.cc",
- "win/wrapped_window_proc_unittest.cc",
- ]
-
- defines = []
-
- deps = [
- ":base",
- ":i18n",
- "//base/allocator:buildflags",
- "//base/test:native_library_test_utils",
- "//base/test:run_all_base_unittests",
- "//base/test:test_support",
- "//base/third_party/dynamic_annotations",
- "//testing/gmock",
- "//testing/gtest",
- "//third_party/icu",
- ]
-
- data_deps = [
- "//base/test:test_child_process",
- "//base/test:test_shared_library",
- ]
-
- if (is_ios || is_mac) {
- deps += [ ":base_unittests_arc" ]
- }
-
- public_deps = [
- ":base_unittests_bundle_data",
- ]
-
- data = [
- "test/data/",
- ]
-
- if (is_posix) {
- sources += [
- "files/dir_reader_posix_unittest.cc",
- "files/file_descriptor_watcher_posix_unittest.cc",
- "message_loop/message_loop_io_posix_unittest.cc",
- "posix/file_descriptor_shuffle_unittest.cc",
- "posix/unix_domain_socket_unittest.cc",
- "task_scheduler/task_tracker_posix_unittest.cc",
- ]
- }
-
- # Allow more direct string conversions on platforms with native utf8
- # strings
- if (is_mac || is_ios || is_chromeos || is_chromecast || is_fuchsia) {
- defines += [ "SYSTEM_NATIVE_UTF8" ]
- }
-
- if (is_android) {
- # Add unwind tables in base_unittests_apk test apk. The unwind tables are
- # generated from debug info in the binary. Removing "default_symbols" and
- # adding symbols config removes the "strip_debug" config that strips the
- # debug info, on base unittests apk.
- if (can_unwind_with_cfi_table) {
- configs -= [ "//build/config/compiler:default_symbols" ]
- if (symbol_level == 2) {
- configs += [ "//build/config/compiler:symbols" ]
- } else {
- configs += [ "//build/config/compiler:minimal_symbols" ]
- }
- add_unwind_tables_in_apk = true
- sources += [ "trace_event/cfi_backtrace_android_unittest.cc" ]
- }
- sources -= [
- "process/process_unittest.cc",
- "process/process_util_unittest.cc",
- ]
- deps += [
- ":base_java",
- ":base_java_unittest_support",
- "//base/test:test_support_java",
- ]
- }
-
- if (is_ios) {
- sources -= [
- "files/file_path_watcher_unittest.cc",
- "memory/discardable_shared_memory_unittest.cc",
- "memory/shared_memory_unittest.cc",
- "process/memory_unittest.cc",
- "process/process_unittest.cc",
- "process/process_util_unittest.cc",
- "sync_socket_unittest.cc",
- "synchronization/waitable_event_watcher_unittest.cc",
- ]
-
- # Pull in specific Mac files for iOS (which have been filtered out by file
- # name rules).
- set_sources_assignment_filter([])
- sources += [
- "mac/bind_objc_block_unittest.mm",
- "mac/foundation_util_unittest.mm",
- "mac/objc_release_properties_unittest.mm",
- "mac/scoped_nsobject_unittest.mm",
- "strings/sys_string_conversions_mac_unittest.mm",
- ]
- set_sources_assignment_filter(sources_assignment_filter)
-
- # TODO(GYP): dep on copy_test_data_ios action.
- }
-
- if (use_partition_alloc) {
- sources += [
- "allocator/partition_allocator/address_space_randomization_unittest.cc",
- "allocator/partition_allocator/page_allocator_unittest.cc",
- "allocator/partition_allocator/partition_alloc_unittest.cc",
- "allocator/partition_allocator/spin_lock_unittest.cc",
- ]
- }
-
- if (is_mac) {
- libs = [
- "CoreFoundation.framework",
- "Foundation.framework",
- ]
- if (current_cpu == "x64") {
- data_deps += [ ":base_profiler_test_support_library" ]
- }
- }
-
- if (is_linux) {
- if (is_desktop_linux) {
- sources += [ "nix/xdg_util_unittest.cc" ]
- }
-
- deps += [ "//base/test:malloc_wrapper" ]
- defines += [
- # This library is used by ElfReaderTest to test reading elf files.
- "MALLOC_WRAPPER_LIB=\"${shlib_prefix}malloc_wrapper${shlib_extension}\"",
- ]
-
- if (!is_component_build) {
- # Set rpath to find libmalloc_wrapper.so even in a non-component build.
- configs += [ "//build/config/gcc:rpath_for_built_shared_libraries" ]
- }
- }
-
- if (!use_glib) {
- sources -= [ "message_loop/message_pump_glib_unittest.cc" ]
- }
-
- if (use_libevent) {
- sources += [ "message_loop/message_pump_libevent_unittest.cc" ]
- deps += [ "//base/third_party/libevent" ]
- }
-
- if (is_fuchsia) {
- sources += [
- "files/dir_reader_posix_unittest.cc",
- "files/file_descriptor_watcher_posix_unittest.cc",
- "fuchsia/services_directory_unittest.cc",
- "message_loop/message_loop_io_posix_unittest.cc",
- "posix/file_descriptor_shuffle_unittest.cc",
- "task_scheduler/task_tracker_posix_unittest.cc",
- ]
-
- sources += [ "fuchsia/async_dispatcher_unittest.cc" ]
- deps += [
- ":test_fidl",
- "//third_party/fuchsia-sdk:async",
- "//third_party/fuchsia-sdk:async_default",
- "//third_party/fuchsia-sdk:fdio",
- ]
- }
-
- if (!is_fuchsia && !is_ios) {
- sources += [ "files/file_locking_unittest.cc" ]
- }
-
- if (is_android) {
- deps += [ "//testing/android/native_test:native_test_native_code" ]
- set_sources_assignment_filter([])
- sources += [
- "debug/elf_reader_linux_unittest.cc",
- "debug/proc_maps_linux_unittest.cc",
- "trace_event/trace_event_android_unittest.cc",
- ]
- set_sources_assignment_filter(sources_assignment_filter)
- }
-
- if (is_win) {
- deps += [ "//base:scoped_handle_test_dll" ]
- if (current_cpu == "x64") {
- sources += [ "profiler/win32_stack_frame_unwinder_unittest.cc" ]
- data_deps += [ ":base_profiler_test_support_library" ]
- }
- }
-
- if (use_allocator_shim) {
- sources += [
- "allocator/allocator_shim_unittest.cc",
- "sampling_heap_profiler/sampling_heap_profiler_unittest.cc",
- ]
- }
-
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
-
- # Symbols for crashes when running tests on swarming.
- if (symbol_level > 0) {
- if (is_win) {
- data += [ "$root_out_dir/base_unittests.exe.pdb" ]
- } else if (is_mac) {
- # TODO(crbug.com/330301): make this conditional on mac_strip_release.
- # data += [ "$root_out_dir/base_unittests.dSYM/" ]
- }
- }
-}
-
-action("build_date") {
- script = "//build/write_build_date_header.py"
-
- # Force recalculation if there's been a change.
- inputs = [
- "//build/util/LASTCHANGE",
- ]
- outputs = [
- "$target_gen_dir/generated_build_date.h",
- ]
-
- args =
- [ rebase_path("$target_gen_dir/generated_build_date.h", root_build_dir) ]
-
- if (is_official_build) {
- args += [ "official" ]
- } else {
- args += [ "default" ]
- }
-
- if (override_build_date != "N/A") {
- args += [ override_build_date ]
- }
-}
-
-if (enable_nocompile_tests) {
- nocompile_test("base_nocompile_tests") {
- sources = [
- "bind_unittest.nc",
- "callback_list_unittest.nc",
- "callback_unittest.nc",
- "containers/span_unittest.nc",
- "memory/ref_counted_unittest.nc",
- "memory/weak_ptr_unittest.nc",
- "metrics/field_trial_params_unittest.nc",
- "metrics/histogram_unittest.nc",
- "optional_unittest.nc",
- "strings/string16_unittest.nc",
- "task_scheduler/task_traits_unittest.nc",
- "thread_annotations_unittest.nc",
- ]
-
- deps = [
- ":base",
- "//base/test:run_all_unittests",
- "//testing/gtest",
- ]
- }
-}
-
-if (is_android) {
- generate_jni("base_jni_headers") {
- sources = [
- "android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java",
- "android/java/src/org/chromium/base/ApkAssets.java",
- "android/java/src/org/chromium/base/ApplicationStatus.java",
- "android/java/src/org/chromium/base/BuildInfo.java",
- "android/java/src/org/chromium/base/Callback.java",
- "android/java/src/org/chromium/base/CommandLine.java",
- "android/java/src/org/chromium/base/ContentUriUtils.java",
- "android/java/src/org/chromium/base/CpuFeatures.java",
- "android/java/src/org/chromium/base/EarlyTraceEvent.java",
- "android/java/src/org/chromium/base/EventLog.java",
- "android/java/src/org/chromium/base/FieldTrialList.java",
- "android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
- "android/java/src/org/chromium/base/JNIUtils.java",
- "android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "android/java/src/org/chromium/base/JavaHandlerThread.java",
- "android/java/src/org/chromium/base/LocaleUtils.java",
- "android/java/src/org/chromium/base/MemoryPressureListener.java",
- "android/java/src/org/chromium/base/PathService.java",
- "android/java/src/org/chromium/base/PathUtils.java",
- "android/java/src/org/chromium/base/PowerMonitor.java",
- "android/java/src/org/chromium/base/SysUtils.java",
- "android/java/src/org/chromium/base/SystemMessageHandler.java",
- "android/java/src/org/chromium/base/ThreadUtils.java",
- "android/java/src/org/chromium/base/ThrowUncaughtException.java",
- "android/java/src/org/chromium/base/TimeUtils.java",
- "android/java/src/org/chromium/base/TimezoneUtils.java",
- "android/java/src/org/chromium/base/TraceEvent.java",
- "android/java/src/org/chromium/base/UnguessableToken.java",
- "android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
- "android/java/src/org/chromium/base/metrics/RecordHistogram.java",
- "android/java/src/org/chromium/base/metrics/RecordUserAction.java",
- "android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
- "android/java/src/org/chromium/base/process_launcher/ChildProcessService.java",
- ]
-
- public_deps = [
- ":android_runtime_jni_headers",
- ]
-
- jni_package = "base"
- }
-
- generate_jar_jni("android_runtime_jni_headers") {
- jni_package = "base"
- classes = [ "java/lang/Runtime.class" ]
- }
-
- android_library("base_java") {
- srcjar_deps = [
- ":base_android_java_enums_srcjar",
- ":base_build_config_gen",
- ":base_java_aidl",
- ":base_native_libraries_gen",
- ]
-
- deps = [
- "//third_party/android_tools:android_support_annotations_java",
- "//third_party/android_tools:android_support_multidex_java",
- "//third_party/android_tools:android_support_v4_java",
- "//third_party/jsr-305:jsr_305_javalib",
- ]
-
- java_files = [
- "android/java/src/org/chromium/base/ActivityState.java",
- "android/java/src/org/chromium/base/AnimationFrameTimeHistogram.java",
- "android/java/src/org/chromium/base/ApiCompatibilityUtils.java",
- "android/java/src/org/chromium/base/ApkAssets.java",
- "android/java/src/org/chromium/base/ApplicationStatus.java",
- "android/java/src/org/chromium/base/BaseSwitches.java",
- "android/java/src/org/chromium/base/BuildInfo.java",
- "android/java/src/org/chromium/base/Callback.java",
- "android/java/src/org/chromium/base/CollectionUtil.java",
- "android/java/src/org/chromium/base/CommandLine.java",
- "android/java/src/org/chromium/base/CommandLineInitUtil.java",
- "android/java/src/org/chromium/base/ContentUriUtils.java",
- "android/java/src/org/chromium/base/ContextUtils.java",
- "android/java/src/org/chromium/base/CpuFeatures.java",
- "android/java/src/org/chromium/base/DiscardableReferencePool.java",
- "android/java/src/org/chromium/base/EarlyTraceEvent.java",
- "android/java/src/org/chromium/base/EventLog.java",
- "android/java/src/org/chromium/base/FieldTrialList.java",
- "android/java/src/org/chromium/base/FileUtils.java",
- "android/java/src/org/chromium/base/ImportantFileWriterAndroid.java",
- "android/java/src/org/chromium/base/JNIUtils.java",
- "android/java/src/org/chromium/base/JavaExceptionReporter.java",
- "android/java/src/org/chromium/base/JavaHandlerThread.java",
- "android/java/src/org/chromium/base/LocaleUtils.java",
- "android/java/src/org/chromium/base/Log.java",
- "android/java/src/org/chromium/base/MemoryPressureListener.java",
- "android/java/src/org/chromium/base/NonThreadSafe.java",
- "android/java/src/org/chromium/base/ObserverList.java",
- "android/java/src/org/chromium/base/PackageUtils.java",
- "android/java/src/org/chromium/base/PathService.java",
- "android/java/src/org/chromium/base/PathUtils.java",
- "android/java/src/org/chromium/base/PowerMonitor.java",
- "android/java/src/org/chromium/base/Promise.java",
- "android/java/src/org/chromium/base/ResourceExtractor.java",
- "android/java/src/org/chromium/base/SecureRandomInitializer.java",
- "android/java/src/org/chromium/base/StreamUtil.java",
- "android/java/src/org/chromium/base/StrictModeContext.java",
- "android/java/src/org/chromium/base/Supplier.java",
- "android/java/src/org/chromium/base/SysUtils.java",
- "android/java/src/org/chromium/base/SystemMessageHandler.java",
- "android/java/src/org/chromium/base/ThreadUtils.java",
- "android/java/src/org/chromium/base/ThrowUncaughtException.java",
- "android/java/src/org/chromium/base/TimeUtils.java",
- "android/java/src/org/chromium/base/TimezoneUtils.java",
- "android/java/src/org/chromium/base/TraceEvent.java",
- "android/java/src/org/chromium/base/UnguessableToken.java",
- "android/java/src/org/chromium/base/VisibleForTesting.java",
- "android/java/src/org/chromium/base/annotations/AccessedByNative.java",
- "android/java/src/org/chromium/base/annotations/CalledByNative.java",
- "android/java/src/org/chromium/base/annotations/CalledByNativeUnchecked.java",
- "android/java/src/org/chromium/base/annotations/JNIAdditionalImport.java",
- "android/java/src/org/chromium/base/annotations/JNINamespace.java",
- "android/java/src/org/chromium/base/annotations/MainDex.java",
- "android/java/src/org/chromium/base/annotations/NativeCall.java",
- "android/java/src/org/chromium/base/annotations/NativeClassQualifiedName.java",
- "android/java/src/org/chromium/base/annotations/RemovableInRelease.java",
- "android/java/src/org/chromium/base/annotations/UsedByReflection.java",
- "android/java/src/org/chromium/base/library_loader/LegacyLinker.java",
- "android/java/src/org/chromium/base/library_loader/LibraryLoader.java",
- "android/java/src/org/chromium/base/library_loader/Linker.java",
- "android/java/src/org/chromium/base/library_loader/LoaderErrors.java",
- "android/java/src/org/chromium/base/library_loader/NativeLibraryPreloader.java",
- "android/java/src/org/chromium/base/library_loader/ProcessInitException.java",
- "android/java/src/org/chromium/base/metrics/CachedMetrics.java",
- "android/java/src/org/chromium/base/metrics/RecordHistogram.java",
- "android/java/src/org/chromium/base/metrics/RecordUserAction.java",
- "android/java/src/org/chromium/base/metrics/StatisticsRecorderAndroid.java",
- "android/java/src/org/chromium/base/multidex/ChromiumMultiDexInstaller.java",
- "android/java/src/org/chromium/base/process_launcher/ChildConnectionAllocator.java",
- "android/java/src/org/chromium/base/process_launcher/ChildProcessConnection.java",
- "android/java/src/org/chromium/base/process_launcher/ChildProcessConstants.java",
- "android/java/src/org/chromium/base/process_launcher/ChildProcessLauncher.java",
- "android/java/src/org/chromium/base/process_launcher/ChildProcessService.java",
- "android/java/src/org/chromium/base/process_launcher/ChildProcessServiceDelegate.java",
- "android/java/src/org/chromium/base/process_launcher/FileDescriptorInfo.java",
- "android/java/src/org/chromium/base/memory/MemoryPressureMonitor.java",
- "android/java/src/org/chromium/base/memory/MemoryPressureCallback.java",
- "android/java/src/org/chromium/base/memory/MemoryPressureUma.java",
- ]
-
- # New versions of BuildConfig.java and NativeLibraries.java
- # (with the actual correct values) will be created when creating an apk.
- jar_excluded_patterns = [
- "*/BuildConfig.class",
- "*/NativeLibraries.class",
- "*/NativeLibraries##*.class",
- ]
- }
-
- android_aidl("base_java_aidl") {
- import_include = [ "android/java/src" ]
- sources = [
- "android/java/src/org/chromium/base/process_launcher/ICallbackInt.aidl",
- "android/java/src/org/chromium/base/process_launcher/IChildProcessService.aidl",
- ]
- }
-
- android_library("base_javatests") {
- testonly = true
- deps = [
- ":base_java",
- ":base_java_test_support",
- "//third_party/android_support_test_runner:runner_java",
- "//third_party/junit:junit",
- ]
- java_files = [
- "android/javatests/src/org/chromium/base/AdvancedMockContextTest.java",
- "android/javatests/src/org/chromium/base/ApiCompatibilityUtilsTest.java",
- "android/javatests/src/org/chromium/base/CommandLineInitUtilTest.java",
- "android/javatests/src/org/chromium/base/CommandLineTest.java",
- "android/javatests/src/org/chromium/base/EarlyTraceEventTest.java",
-
- # TODO(nona): move to Junit once that is built for Android N.
- "android/javatests/src/org/chromium/base/LocaleUtilsTest.java",
- "android/javatests/src/org/chromium/base/ObserverListTest.java",
- "android/javatests/src/org/chromium/base/StrictModeContextTest.java",
- "android/javatests/src/org/chromium/base/metrics/RecordHistogramTest.java",
- ]
- }
-
- android_library("base_java_test_support") {
- testonly = true
- deps = [
- ":base_java",
- "//testing/android/reporter:reporter_java",
- "//third_party/android_support_test_runner:exposed_instrumentation_api_publish_java",
- "//third_party/android_support_test_runner:rules_java",
- "//third_party/android_support_test_runner:runner_java",
- "//third_party/android_tools:android_support_annotations_java",
- "//third_party/android_tools:android_support_chromium_java",
- "//third_party/android_tools:android_support_compat_java",
- "//third_party/hamcrest:hamcrest_core_java",
- "//third_party/junit",
- "//third_party/ub-uiautomator:ub_uiautomator_java",
- ]
-
- deps += android_extra_test_deps
-
- java_files = [
- "test/android/javatests/src/org/chromium/base/test/BaseJUnit4ClassRunner.java",
- "test/android/javatests/src/org/chromium/base/test/BaseChromiumAndroidJUnitRunner.java",
- "test/android/javatests/src/org/chromium/base/test/BaseChromiumRunnerCommon.java",
- "test/android/javatests/src/org/chromium/base/test/BaseTestResult.java",
- "test/android/javatests/src/org/chromium/base/test/ScreenshotOnFailureStatement.java",
- "test/android/javatests/src/org/chromium/base/test/SetUpTestRule.java",
- "test/android/javatests/src/org/chromium/base/test/SetUpStatement.java",
- "test/android/javatests/src/org/chromium/base/test/TestListInstrumentationRunListener.java",
- "test/android/javatests/src/org/chromium/base/test/TestTraceEvent.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunner.java",
- "test/android/javatests/src/org/chromium/base/test/params/BlockJUnit4RunnerDelegate.java",
- "test/android/javatests/src/org/chromium/base/test/params/BaseJUnit4RunnerDelegate.java",
- "test/android/javatests/src/org/chromium/base/test/params/MethodParamAnnotationRule.java",
- "test/android/javatests/src/org/chromium/base/test/params/MethodParamRule.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterAnnotations.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterizedFrameworkMethod.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegate.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommon.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactory.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterProvider.java",
- "test/android/javatests/src/org/chromium/base/test/params/ParameterSet.java",
- "test/android/javatests/src/org/chromium/base/test/util/AdvancedMockContext.java",
- "test/android/javatests/src/org/chromium/base/test/util/AnnotationRule.java",
- "test/android/javatests/src/org/chromium/base/test/util/CallbackHelper.java",
- "test/android/javatests/src/org/chromium/base/test/util/CommandLineFlags.java",
- "test/android/javatests/src/org/chromium/base/test/util/DisableIf.java",
- "test/android/javatests/src/org/chromium/base/test/util/DisableIfSkipCheck.java",
- "test/android/javatests/src/org/chromium/base/test/util/AnnotationProcessingUtils.java",
- "test/android/javatests/src/org/chromium/base/test/util/DisabledTest.java",
- "test/android/javatests/src/org/chromium/base/test/util/EnormousTest.java",
- "test/android/javatests/src/org/chromium/base/test/util/Feature.java",
- "test/android/javatests/src/org/chromium/base/test/util/FlakyTest.java",
- "test/android/javatests/src/org/chromium/base/test/util/InMemorySharedPreferences.java",
- "test/android/javatests/src/org/chromium/base/test/util/InstrumentationUtils.java",
- "test/android/javatests/src/org/chromium/base/test/util/IntegrationTest.java",
- "test/android/javatests/src/org/chromium/base/test/util/Manual.java",
- "test/android/javatests/src/org/chromium/base/test/util/ManualSkipCheck.java",
- "test/android/javatests/src/org/chromium/base/test/util/Matchers.java",
- "test/android/javatests/src/org/chromium/base/test/util/MetricsUtils.java",
- "test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevel.java",
- "test/android/javatests/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheck.java",
- "test/android/javatests/src/org/chromium/base/test/util/Restriction.java",
- "test/android/javatests/src/org/chromium/base/test/util/RestrictionSkipCheck.java",
- "test/android/javatests/src/org/chromium/base/test/util/RetryOnFailure.java",
- "test/android/javatests/src/org/chromium/base/test/util/ScalableTimeout.java",
- "test/android/javatests/src/org/chromium/base/test/util/SkipCheck.java",
- "test/android/javatests/src/org/chromium/base/test/util/TestFileUtil.java",
- "test/android/javatests/src/org/chromium/base/test/util/TestThread.java",
- "test/android/javatests/src/org/chromium/base/test/util/TimeoutScale.java",
- "test/android/javatests/src/org/chromium/base/test/util/UserActionTester.java",
- "test/android/javatests/src/org/chromium/base/test/util/UrlUtils.java",
- "test/android/javatests/src/org/chromium/base/test/util/parameter/CommandLineParameter.java",
- "test/android/javatests/src/org/chromium/base/test/util/parameter/SkipCommandLineParameterization.java",
- ]
- }
-
- android_library("base_java_process_launcher_test_support") {
- testonly = true
- deps = [
- ":base_java",
- ":base_java_test_support",
- ]
- java_files = [ "test/android/javatests/src/org/chromium/base/test/TestChildProcessConnection.java" ]
- }
-
- android_library("base_junit_test_support") {
- # Plaform checks are broken for Robolectric.
- bypass_platform_checks = true
- testonly = true
- java_files = [
- "android/junit/src/org/chromium/base/metrics/test/ShadowRecordHistogram.java",
- "test/android/junit/src/org/chromium/base/test/BaseRobolectricTestRunner.java",
- ]
- deps = [
- ":base_java",
- "//testing/android/junit:junit_test_support",
- "//third_party/robolectric:robolectric_all_java",
- ]
- }
-
- junit_binary("base_junit_tests") {
- java_files = [
- "android/junit/src/org/chromium/base/ApplicationStatusTest.java",
- "android/junit/src/org/chromium/base/DiscardableReferencePoolTest.java",
- "android/junit/src/org/chromium/base/LogTest.java",
- "android/junit/src/org/chromium/base/NonThreadSafeTest.java",
- "android/junit/src/org/chromium/base/PromiseTest.java",
- "android/junit/src/org/chromium/base/memory/MemoryPressureMonitorTest.java",
- "android/junit/src/org/chromium/base/process_launcher/ChildConnectionAllocatorTest.java",
- "android/junit/src/org/chromium/base/process_launcher/ChildProcessConnectionTest.java",
- "test/android/junit/src/org/chromium/base/test/SetUpStatementTest.java",
- "test/android/junit/src/org/chromium/base/test/TestListInstrumentationRunListenerTest.java",
- "test/android/junit/src/org/chromium/base/test/util/AnnotationProcessingUtilsTest.java",
- "test/android/junit/src/org/chromium/base/test/util/DisableIfTest.java",
- "test/android/junit/src/org/chromium/base/test/util/ManualSkipCheckTest.java",
- "test/android/junit/src/org/chromium/base/test/util/MinAndroidSdkLevelSkipCheckTest.java",
- "test/android/junit/src/org/chromium/base/test/util/RestrictionSkipCheckTest.java",
- "test/android/junit/src/org/chromium/base/test/util/SkipCheckTest.java",
- "test/android/junit/src/org/chromium/base/test/params/ExampleParameterizedTest.java",
- "test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerTest.java",
- "test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateCommonTest.java",
- "test/android/junit/src/org/chromium/base/test/params/ParameterizedRunnerDelegateFactoryTest.java",
- "test/android/junit/src/org/chromium/base/test/params/ParameterizedTestNameTest.java",
- ]
- deps = [
- ":base_java",
- ":base_java_process_launcher_test_support",
- ":base_java_test_support",
- ":base_junit_test_support",
- "//third_party/hamcrest:hamcrest_java",
- ]
- }
-
- java_cpp_enum("base_android_java_enums_srcjar") {
- sources = [
- "android/application_status_listener.h",
- "android/library_loader/library_load_from_apk_status_codes.h",
- "android/library_loader/library_loader_hooks.h",
- "memory/memory_pressure_listener.h",
- "metrics/histogram_base.h",
- "trace_event/trace_config.h",
- ]
- }
-
- generate_build_config_srcjar("base_build_config_gen") {
- use_final_fields = false
- }
-
- java_cpp_template("base_native_libraries_gen") {
- sources = [
- "android/java/templates/NativeLibraries.template",
- ]
- package_path = "org/chromium/base/library_loader"
- }
-
- android_library("base_java_unittest_support") {
- testonly = true
- deps = [
- ":base_java",
- ]
- java_files = [
- "test/android/java/src/org/chromium/base/ContentUriTestUtils.java",
- "test/android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java",
- ]
- }
-}
-
-# Keep the list of fuzzer_tests in alphabetical order.
-fuzzer_test("base64_decode_fuzzer") {
- sources = [
- "base64_decode_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
-}
-
-fuzzer_test("base64_encode_fuzzer") {
- sources = [
- "base64_encode_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
-}
-
-fuzzer_test("base_json_correctness_fuzzer") {
- sources = [
- "json/json_correctness_fuzzer.cc",
- ]
- deps = [
- ":base",
- ]
- dict = "//testing/libfuzzer/fuzzers/dicts/json.dict"
-}
-
-fuzzer_test("base_json_reader_fuzzer") {
- sources = [
- "json/json_reader_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
- dict = "//testing/libfuzzer/fuzzers/dicts/json.dict"
-}
-
-fuzzer_test("base_json_string_escape_fuzzer") {
- sources = [
- "json/string_escape_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
-}
-
-fuzzer_test("string_number_conversions_fuzzer") {
- sources = [
- "strings/string_number_conversions_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
-}
-
-fuzzer_test("string_tokenizer_fuzzer") {
- sources = [
- "strings/string_tokenizer_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
-}
-
-fuzzer_test("utf_string_conversions_fuzzer") {
- sources = [
- "strings/utf_string_conversions_fuzzer.cc",
- ]
- deps = [
- "//base",
- ]
-}
-
-# TODO(dyaroshev): remove regression fuzzer, after we run it for a few days
-# and are confident that the transition was ok.
-fuzzer_test("utf_string_conversions_regression_fuzzer") {
- sources = [
- "strings/old_utf_string_conversions.cc",
- "strings/old_utf_string_conversions.h",
- "strings/utf_string_conversions_regression_fuzzer.cc",
- ]
- deps = [
- ":base",
- ]
-
- libfuzzer_options = [ "max_len=32" ]
-}
diff --git a/base/allocator/BUILD.gn b/base/allocator/BUILD.gn
deleted file mode 100644
index 636a342..0000000
--- a/base/allocator/BUILD.gn
+++ /dev/null
@@ -1,284 +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.
-
-import("//build/buildflag_header.gni")
-import("//build/config/allocator.gni")
-import("//build/config/compiler/compiler.gni")
-
-declare_args() {
- # Provide a way to force disable debugallocation in Debug builds,
- # e.g. for profiling (it's more rare to profile Debug builds,
- # but people sometimes need to do that).
- enable_debugallocation = is_debug
-}
-
-# This "allocator" meta-target will forward to the default allocator according
-# to the build settings.
-group("allocator") {
- public_deps = []
- deps = []
-
- if (use_allocator == "tcmalloc") {
- deps += [ ":tcmalloc" ]
- }
-}
-
-config("tcmalloc_flags") {
- defines = []
- if (enable_debugallocation) {
- defines += [
- # Use debugallocation for Debug builds to catch problems early
- # and cleanly, http://crbug.com/30715 .
- "TCMALLOC_FOR_DEBUGALLOCATION",
- ]
- }
- if (use_allocator_shim) {
- defines += [ "TCMALLOC_DONT_REPLACE_SYSTEM_ALLOC" ]
- }
- if (is_clang) {
- cflags = [
- # tcmalloc initializes some fields in the wrong order.
- "-Wno-reorder",
-
- # tcmalloc contains some unused local template specializations.
- "-Wno-unused-function",
-
- # tcmalloc uses COMPILE_ASSERT without static_assert but with typedefs.
- "-Wno-unused-local-typedefs",
-
- # for magic2_ in debugallocation.cc (only built in Debug builds) typedefs.
- "-Wno-unused-private-field",
- ]
- } else {
- cflags = []
- }
-
- if (is_linux || is_android) {
- # We enable all warnings by default, but upstream disables a few.
- # Keep "-Wno-*" flags in sync with upstream by comparing against:
- # http://code.google.com/p/google-perftools/source/browse/trunk/Makefile.am
- cflags += [
- "-Wno-sign-compare",
- "-Wno-unused-result",
- ]
- }
-}
-
-if (use_allocator == "tcmalloc") {
- # tcmalloc currently won't compile on Android.
- source_set("tcmalloc") {
- tcmalloc_dir = "//third_party/tcmalloc/chromium"
-
- # Don't check tcmalloc's includes. These files include various files like
- # base/foo.h and they actually refer to tcmalloc's forked copy of base
- # rather than the regular one, which confuses the header checker.
- check_includes = false
-
- sources = [
- # Generated for our configuration from tcmalloc's build
- # and checked in.
- "$tcmalloc_dir/src/config.h",
- "$tcmalloc_dir/src/config_android.h",
- "$tcmalloc_dir/src/config_linux.h",
- "$tcmalloc_dir/src/config_win.h",
-
- # tcmalloc native and forked files.
- "$tcmalloc_dir/src/base/abort.cc",
- "$tcmalloc_dir/src/base/abort.h",
- "$tcmalloc_dir/src/base/arm_instruction_set_select.h",
- "$tcmalloc_dir/src/base/atomicops-internals-arm-generic.h",
- "$tcmalloc_dir/src/base/atomicops-internals-arm-v6plus.h",
- "$tcmalloc_dir/src/base/atomicops-internals-linuxppc.h",
- "$tcmalloc_dir/src/base/atomicops-internals-macosx.h",
- "$tcmalloc_dir/src/base/atomicops-internals-windows.h",
- "$tcmalloc_dir/src/base/atomicops-internals-x86.cc",
- "$tcmalloc_dir/src/base/atomicops-internals-x86.h",
- "$tcmalloc_dir/src/base/atomicops.h",
- "$tcmalloc_dir/src/base/commandlineflags.h",
- "$tcmalloc_dir/src/base/cycleclock.h",
-
- # We don't list dynamic_annotations.c since its copy is already
- # present in the dynamic_annotations target.
- "$tcmalloc_dir/src/base/elf_mem_image.cc",
- "$tcmalloc_dir/src/base/elf_mem_image.h",
- "$tcmalloc_dir/src/base/linuxthreads.cc",
- "$tcmalloc_dir/src/base/linuxthreads.h",
- "$tcmalloc_dir/src/base/logging.cc",
- "$tcmalloc_dir/src/base/logging.h",
- "$tcmalloc_dir/src/base/low_level_alloc.cc",
- "$tcmalloc_dir/src/base/low_level_alloc.h",
- "$tcmalloc_dir/src/base/spinlock.cc",
- "$tcmalloc_dir/src/base/spinlock.h",
- "$tcmalloc_dir/src/base/spinlock_internal.cc",
- "$tcmalloc_dir/src/base/spinlock_internal.h",
- "$tcmalloc_dir/src/base/synchronization_profiling.h",
- "$tcmalloc_dir/src/base/sysinfo.cc",
- "$tcmalloc_dir/src/base/sysinfo.h",
- "$tcmalloc_dir/src/base/vdso_support.cc",
- "$tcmalloc_dir/src/base/vdso_support.h",
- "$tcmalloc_dir/src/central_freelist.cc",
- "$tcmalloc_dir/src/central_freelist.h",
- "$tcmalloc_dir/src/common.cc",
- "$tcmalloc_dir/src/common.h",
-
- # #included by debugallocation_shim.cc
- #"$tcmalloc_dir/src/debugallocation.cc",
- "$tcmalloc_dir/src/free_list.cc",
- "$tcmalloc_dir/src/free_list.h",
- "$tcmalloc_dir/src/gperftools/heap-profiler.h",
- "$tcmalloc_dir/src/gperftools/malloc_extension.h",
- "$tcmalloc_dir/src/gperftools/malloc_hook.h",
- "$tcmalloc_dir/src/gperftools/stacktrace.h",
- "$tcmalloc_dir/src/heap-profile-table.cc",
- "$tcmalloc_dir/src/heap-profile-table.h",
- "$tcmalloc_dir/src/heap-profiler.cc",
- "$tcmalloc_dir/src/internal_logging.cc",
- "$tcmalloc_dir/src/internal_logging.h",
- "$tcmalloc_dir/src/linked_list.h",
- "$tcmalloc_dir/src/malloc_extension.cc",
- "$tcmalloc_dir/src/malloc_hook-inl.h",
- "$tcmalloc_dir/src/malloc_hook.cc",
- "$tcmalloc_dir/src/maybe_threads.cc",
- "$tcmalloc_dir/src/maybe_threads.h",
- "$tcmalloc_dir/src/memory_region_map.cc",
- "$tcmalloc_dir/src/memory_region_map.h",
- "$tcmalloc_dir/src/page_heap.cc",
- "$tcmalloc_dir/src/page_heap.h",
- "$tcmalloc_dir/src/raw_printer.cc",
- "$tcmalloc_dir/src/raw_printer.h",
- "$tcmalloc_dir/src/sampler.cc",
- "$tcmalloc_dir/src/sampler.h",
- "$tcmalloc_dir/src/span.cc",
- "$tcmalloc_dir/src/span.h",
- "$tcmalloc_dir/src/stack_trace_table.cc",
- "$tcmalloc_dir/src/stack_trace_table.h",
- "$tcmalloc_dir/src/stacktrace.cc",
- "$tcmalloc_dir/src/static_vars.cc",
- "$tcmalloc_dir/src/static_vars.h",
- "$tcmalloc_dir/src/symbolize.cc",
- "$tcmalloc_dir/src/symbolize.h",
- "$tcmalloc_dir/src/system-alloc.cc",
- "$tcmalloc_dir/src/system-alloc.h",
-
- # #included by debugallocation_shim.cc
- #"$tcmalloc_dir/src/tcmalloc.cc",
- #"$tcmalloc_dir/src/tcmalloc.h",
- "$tcmalloc_dir/src/thread_cache.cc",
- "$tcmalloc_dir/src/thread_cache.h",
- "$tcmalloc_dir/src/windows/port.cc",
- "$tcmalloc_dir/src/windows/port.h",
- "debugallocation_shim.cc",
-
- # These are both #included by allocator_shim for maximal linking.
- #"generic_allocators.cc",
- #"win_allocator.cc",
- ]
-
- # Not included on mips64el.
- if (current_cpu == "mips64el") {
- sources -= [
- "$tcmalloc_dir/src/base/linuxthreads.cc",
- "$tcmalloc_dir/src/base/linuxthreads.h",
- ]
- }
-
- # Disable the heap checker in tcmalloc.
- defines = [ "NO_HEAP_CHECK" ]
-
- include_dirs = [
- ".",
- "$tcmalloc_dir/src/base",
- "$tcmalloc_dir/src",
- ]
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [
- "//build/config/compiler:no_chromium_code",
- ":tcmalloc_flags",
- ]
-
- # Thumb mode disabled due to bug in clang integrated assembler
- # TODO(https://llvm.org/bugs/show_bug.cgi?id=31058)
- configs -= [ "//build/config/compiler:compiler_arm_thumb" ]
- configs += [ "//build/config/compiler:compiler_arm" ]
-
- # TODO(crbug.com/633719) Make tcmalloc work with AFDO on GCC if possible.
- if (!is_clang) {
- configs -= [ "//build/config/compiler:afdo" ]
- }
-
- deps = []
-
- if (enable_profiling) {
- sources += [
- "$tcmalloc_dir/src/base/thread_lister.c",
- "$tcmalloc_dir/src/base/thread_lister.h",
- "$tcmalloc_dir/src/profile-handler.cc",
- "$tcmalloc_dir/src/profile-handler.h",
- "$tcmalloc_dir/src/profiledata.cc",
- "$tcmalloc_dir/src/profiledata.h",
- "$tcmalloc_dir/src/profiler.cc",
- ]
- defines += [ "ENABLE_PROFILING=1" ]
- }
-
- if (is_linux || is_android) {
- sources -= [
- "$tcmalloc_dir/src/system-alloc.h",
- "$tcmalloc_dir/src/windows/port.cc",
- "$tcmalloc_dir/src/windows/port.h",
- ]
-
- # Compiling tcmalloc with -fvisibility=default is only necessary when
- # not using the allocator shim, which provides the correct visibility
- # annotations for those symbols which need to be exported (see
- # //base/allocator/allocator_shim_override_glibc_weak_symbols.h and
- # //base/allocator/allocator_shim_internals.h for the definition of
- # SHIM_ALWAYS_EXPORT).
- if (!use_allocator_shim) {
- configs -= [ "//build/config/gcc:symbol_visibility_hidden" ]
- configs += [ "//build/config/gcc:symbol_visibility_default" ]
- }
-
- ldflags = [
- # Don't let linker rip this symbol out, otherwise the heap&cpu
- # profilers will not initialize properly on startup.
- "-Wl,-uIsHeapProfilerRunning,-uProfilerStart",
-
- # Do the same for heap leak checker.
- "-Wl,-u_Z21InitialMallocHook_NewPKvj,-u_Z22InitialMallocHook_MMapPKvS0_jiiix,-u_Z22InitialMallocHook_SbrkPKvi",
- "-Wl,-u_Z21InitialMallocHook_NewPKvm,-u_Z22InitialMallocHook_MMapPKvS0_miiil,-u_Z22InitialMallocHook_SbrkPKvl",
- "-Wl,-u_ZN15HeapLeakChecker12IgnoreObjectEPKv,-u_ZN15HeapLeakChecker14UnIgnoreObjectEPKv",
- ]
- }
-
- # Make sure the allocation library is optimized as much as possible when
- # we"re in release mode.
- if (!is_debug) {
- configs -= [ "//build/config/compiler:default_optimization" ]
- configs += [ "//build/config/compiler:optimize_max" ]
- }
-
- deps += [ "//base/third_party/dynamic_annotations" ]
- }
-} # use_allocator == "tcmalloc"
-
-buildflag_header("buildflags") {
- header = "buildflags.h"
- flags = [ "USE_ALLOCATOR_SHIM=$use_allocator_shim" ]
-}
-
-# Used to shim malloc symbols on Android. see //base/allocator/README.md.
-config("wrap_malloc_symbols") {
- ldflags = [
- "-Wl,-wrap,calloc",
- "-Wl,-wrap,free",
- "-Wl,-wrap,malloc",
- "-Wl,-wrap,memalign",
- "-Wl,-wrap,posix_memalign",
- "-Wl,-wrap,pvalloc",
- "-Wl,-wrap,realloc",
- "-Wl,-wrap,valloc",
- ]
-}
diff --git a/base/allocator/allocator_shim_unittest.cc b/base/allocator/allocator_shim_unittest.cc
deleted file mode 100644
index 0a18eb2..0000000
--- a/base/allocator/allocator_shim_unittest.cc
+++ /dev/null
@@ -1,460 +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/allocator/allocator_shim.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <memory>
-#include <new>
-#include <vector>
-
-#include "base/allocator/partition_allocator/partition_alloc.h"
-#include "base/atomicops.h"
-#include "base/process/process_metrics.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local.h"
-#include "build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#elif defined(OS_MACOSX)
-#include <malloc/malloc.h>
-#include "base/allocator/allocator_interception_mac.h"
-#include "base/mac/mac_util.h"
-#include "third_party/apple_apsl/malloc.h"
-#else
-#include <malloc.h>
-#endif
-
-#if !defined(OS_WIN)
-#include <unistd.h>
-#endif
-
-// Some new Android NDKs (64 bit) does not expose (p)valloc anymore. These
-// functions are implemented at the shim-layer level.
-#if defined(OS_ANDROID)
-extern "C" {
-void* valloc(size_t size);
-void* pvalloc(size_t size);
-}
-#endif
-
-namespace base {
-namespace allocator {
-namespace {
-
-using testing::MockFunction;
-using testing::_;
-
-class AllocatorShimTest : public testing::Test {
- public:
- static const size_t kMaxSizeTracked = 2 * base::kSystemPageSize;
- AllocatorShimTest() : testing::Test() {}
-
- static size_t Hash(const void* ptr) {
- return reinterpret_cast<uintptr_t>(ptr) % kMaxSizeTracked;
- }
-
- static void* MockAlloc(const AllocatorDispatch* self,
- size_t size,
- void* context) {
- if (instance_ && size < kMaxSizeTracked)
- ++(instance_->allocs_intercepted_by_size[size]);
- return self->next->alloc_function(self->next, size, context);
- }
-
- static void* MockAllocZeroInit(const AllocatorDispatch* self,
- size_t n,
- size_t size,
- void* context) {
- const size_t real_size = n * size;
- if (instance_ && real_size < kMaxSizeTracked)
- ++(instance_->zero_allocs_intercepted_by_size[real_size]);
- return self->next->alloc_zero_initialized_function(self->next, n, size,
- context);
- }
-
- static void* MockAllocAligned(const AllocatorDispatch* self,
- size_t alignment,
- size_t size,
- void* context) {
- if (instance_) {
- if (size < kMaxSizeTracked)
- ++(instance_->aligned_allocs_intercepted_by_size[size]);
- if (alignment < kMaxSizeTracked)
- ++(instance_->aligned_allocs_intercepted_by_alignment[alignment]);
- }
- return self->next->alloc_aligned_function(self->next, alignment, size,
- context);
- }
-
- static void* MockRealloc(const AllocatorDispatch* self,
- void* address,
- size_t size,
- void* context) {
- if (instance_) {
- // Size 0xFEED a special sentinel for the NewHandlerConcurrency test.
- // Hitting it for the first time will cause a failure, causing the
- // invocation of the std::new_handler.
- if (size == 0xFEED) {
- if (!instance_->did_fail_realloc_0xfeed_once->Get()) {
- instance_->did_fail_realloc_0xfeed_once->Set(true);
- return nullptr;
- } else {
- return address;
- }
- }
-
- if (size < kMaxSizeTracked)
- ++(instance_->reallocs_intercepted_by_size[size]);
- ++instance_->reallocs_intercepted_by_addr[Hash(address)];
- }
- return self->next->realloc_function(self->next, address, size, context);
- }
-
- static void MockFree(const AllocatorDispatch* self,
- void* address,
- void* context) {
- if (instance_) {
- ++instance_->frees_intercepted_by_addr[Hash(address)];
- }
- self->next->free_function(self->next, address, context);
- }
-
- static size_t MockGetSizeEstimate(const AllocatorDispatch* self,
- void* address,
- void* context) {
- return self->next->get_size_estimate_function(self->next, address, context);
- }
-
- static unsigned MockBatchMalloc(const AllocatorDispatch* self,
- size_t size,
- void** results,
- unsigned num_requested,
- void* context) {
- if (instance_) {
- instance_->batch_mallocs_intercepted_by_size[size] =
- instance_->batch_mallocs_intercepted_by_size[size] + num_requested;
- }
- return self->next->batch_malloc_function(self->next, size, results,
- num_requested, context);
- }
-
- static void MockBatchFree(const AllocatorDispatch* self,
- void** to_be_freed,
- unsigned num_to_be_freed,
- void* context) {
- if (instance_) {
- for (unsigned i = 0; i < num_to_be_freed; ++i) {
- ++instance_->batch_frees_intercepted_by_addr[Hash(to_be_freed[i])];
- }
- }
- self->next->batch_free_function(self->next, to_be_freed, num_to_be_freed,
- context);
- }
-
- static void MockFreeDefiniteSize(const AllocatorDispatch* self,
- void* ptr,
- size_t size,
- void* context) {
- if (instance_) {
- ++instance_->frees_intercepted_by_addr[Hash(ptr)];
- ++instance_->free_definite_sizes_intercepted_by_size[size];
- }
- self->next->free_definite_size_function(self->next, ptr, size, context);
- }
-
- static void NewHandler() {
- if (!instance_)
- return;
- subtle::Barrier_AtomicIncrement(&instance_->num_new_handler_calls, 1);
- }
-
- int32_t GetNumberOfNewHandlerCalls() {
- return subtle::Acquire_Load(&instance_->num_new_handler_calls);
- }
-
- void SetUp() override {
- const size_t array_size = kMaxSizeTracked * sizeof(size_t);
- memset(&allocs_intercepted_by_size, 0, array_size);
- memset(&zero_allocs_intercepted_by_size, 0, array_size);
- memset(&aligned_allocs_intercepted_by_size, 0, array_size);
- memset(&aligned_allocs_intercepted_by_alignment, 0, array_size);
- memset(&reallocs_intercepted_by_size, 0, array_size);
- memset(&frees_intercepted_by_addr, 0, array_size);
- memset(&batch_mallocs_intercepted_by_size, 0, array_size);
- memset(&batch_frees_intercepted_by_addr, 0, array_size);
- memset(&free_definite_sizes_intercepted_by_size, 0, array_size);
- did_fail_realloc_0xfeed_once.reset(new ThreadLocalBoolean());
- subtle::Release_Store(&num_new_handler_calls, 0);
- instance_ = this;
-
-#if defined(OS_MACOSX)
- InitializeAllocatorShim();
-#endif
- }
-
- void TearDown() override {
- instance_ = nullptr;
-#if defined(OS_MACOSX)
- UninterceptMallocZonesForTesting();
-#endif
- }
-
- protected:
- size_t allocs_intercepted_by_size[kMaxSizeTracked];
- size_t zero_allocs_intercepted_by_size[kMaxSizeTracked];
- size_t aligned_allocs_intercepted_by_size[kMaxSizeTracked];
- size_t aligned_allocs_intercepted_by_alignment[kMaxSizeTracked];
- size_t reallocs_intercepted_by_size[kMaxSizeTracked];
- size_t reallocs_intercepted_by_addr[kMaxSizeTracked];
- size_t frees_intercepted_by_addr[kMaxSizeTracked];
- size_t batch_mallocs_intercepted_by_size[kMaxSizeTracked];
- size_t batch_frees_intercepted_by_addr[kMaxSizeTracked];
- size_t free_definite_sizes_intercepted_by_size[kMaxSizeTracked];
- std::unique_ptr<ThreadLocalBoolean> did_fail_realloc_0xfeed_once;
- subtle::Atomic32 num_new_handler_calls;
-
- private:
- static AllocatorShimTest* instance_;
-};
-
-struct TestStruct1 {
- uint32_t ignored;
- uint8_t ignored_2;
-};
-
-struct TestStruct2 {
- uint64_t ignored;
- uint8_t ignored_3;
-};
-
-class ThreadDelegateForNewHandlerTest : public PlatformThread::Delegate {
- public:
- ThreadDelegateForNewHandlerTest(WaitableEvent* event) : event_(event) {}
-
- void ThreadMain() override {
- event_->Wait();
- void* temp = malloc(1);
- void* res = realloc(temp, 0xFEED);
- EXPECT_EQ(temp, res);
- }
-
- private:
- WaitableEvent* event_;
-};
-
-AllocatorShimTest* AllocatorShimTest::instance_ = nullptr;
-
-AllocatorDispatch g_mock_dispatch = {
- &AllocatorShimTest::MockAlloc, /* alloc_function */
- &AllocatorShimTest::MockAllocZeroInit, /* alloc_zero_initialized_function */
- &AllocatorShimTest::MockAllocAligned, /* alloc_aligned_function */
- &AllocatorShimTest::MockRealloc, /* realloc_function */
- &AllocatorShimTest::MockFree, /* free_function */
- &AllocatorShimTest::MockGetSizeEstimate, /* get_size_estimate_function */
- &AllocatorShimTest::MockBatchMalloc, /* batch_malloc_function */
- &AllocatorShimTest::MockBatchFree, /* batch_free_function */
- &AllocatorShimTest::MockFreeDefiniteSize, /* free_definite_size_function */
- nullptr, /* next */
-};
-
-TEST_F(AllocatorShimTest, InterceptLibcSymbols) {
- InsertAllocatorDispatch(&g_mock_dispatch);
-
- void* alloc_ptr = malloc(19);
- ASSERT_NE(nullptr, alloc_ptr);
- ASSERT_GE(allocs_intercepted_by_size[19], 1u);
-
- void* zero_alloc_ptr = calloc(2, 23);
- ASSERT_NE(nullptr, zero_alloc_ptr);
- ASSERT_GE(zero_allocs_intercepted_by_size[2 * 23], 1u);
-
-#if !defined(OS_WIN)
- const size_t kPageSize = base::GetPageSize();
- void* posix_memalign_ptr = nullptr;
- int res = posix_memalign(&posix_memalign_ptr, 256, 59);
- ASSERT_EQ(0, res);
- ASSERT_NE(nullptr, posix_memalign_ptr);
- ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(posix_memalign_ptr) % 256);
- ASSERT_GE(aligned_allocs_intercepted_by_alignment[256], 1u);
- ASSERT_GE(aligned_allocs_intercepted_by_size[59], 1u);
-
- void* valloc_ptr = valloc(61);
- ASSERT_NE(nullptr, valloc_ptr);
- ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(valloc_ptr) % kPageSize);
- ASSERT_GE(aligned_allocs_intercepted_by_alignment[kPageSize], 1u);
- ASSERT_GE(aligned_allocs_intercepted_by_size[61], 1u);
-#endif // !OS_WIN
-
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
- void* memalign_ptr = memalign(128, 53);
- ASSERT_NE(nullptr, memalign_ptr);
- ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(memalign_ptr) % 128);
- ASSERT_GE(aligned_allocs_intercepted_by_alignment[128], 1u);
- ASSERT_GE(aligned_allocs_intercepted_by_size[53], 1u);
-
- void* pvalloc_ptr = pvalloc(67);
- ASSERT_NE(nullptr, pvalloc_ptr);
- ASSERT_EQ(0u, reinterpret_cast<uintptr_t>(pvalloc_ptr) % kPageSize);
- ASSERT_GE(aligned_allocs_intercepted_by_alignment[kPageSize], 1u);
- // pvalloc rounds the size up to the next page.
- ASSERT_GE(aligned_allocs_intercepted_by_size[kPageSize], 1u);
-#endif // !OS_WIN && !OS_MACOSX
-
- char* realloc_ptr = static_cast<char*>(malloc(10));
- strcpy(realloc_ptr, "foobar");
- void* old_realloc_ptr = realloc_ptr;
- realloc_ptr = static_cast<char*>(realloc(realloc_ptr, 73));
- ASSERT_GE(reallocs_intercepted_by_size[73], 1u);
- ASSERT_GE(reallocs_intercepted_by_addr[Hash(old_realloc_ptr)], 1u);
- ASSERT_EQ(0, strcmp(realloc_ptr, "foobar"));
-
- free(alloc_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(alloc_ptr)], 1u);
-
- free(zero_alloc_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(zero_alloc_ptr)], 1u);
-
-#if !defined(OS_WIN) && !defined(OS_MACOSX)
- free(memalign_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(memalign_ptr)], 1u);
-
- free(pvalloc_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(pvalloc_ptr)], 1u);
-#endif // !OS_WIN && !OS_MACOSX
-
-#if !defined(OS_WIN)
- free(posix_memalign_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(posix_memalign_ptr)], 1u);
-
- free(valloc_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(valloc_ptr)], 1u);
-#endif // !OS_WIN
-
- free(realloc_ptr);
- ASSERT_GE(frees_intercepted_by_addr[Hash(realloc_ptr)], 1u);
-
- RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
-
- void* non_hooked_ptr = malloc(4095);
- ASSERT_NE(nullptr, non_hooked_ptr);
- ASSERT_EQ(0u, allocs_intercepted_by_size[4095]);
- free(non_hooked_ptr);
-}
-
-#if defined(OS_MACOSX)
-TEST_F(AllocatorShimTest, InterceptLibcSymbolsBatchMallocFree) {
- InsertAllocatorDispatch(&g_mock_dispatch);
-
- unsigned count = 13;
- std::vector<void*> results;
- results.resize(count);
- unsigned result_count = malloc_zone_batch_malloc(malloc_default_zone(), 99,
- results.data(), count);
- ASSERT_EQ(count, result_count);
-
- // TODO(erikchen): On macOS 10.12+, batch_malloc in the default zone may
- // forward to another zone, which we've also shimmed, resulting in
- // MockBatchMalloc getting called twice as often as we'd expect. This
- // re-entrancy into the allocator shim is a bug that needs to be fixed.
- // https://crbug.com/693237.
- // ASSERT_EQ(count, batch_mallocs_intercepted_by_size[99]);
-
- std::vector<void*> results_copy(results);
- malloc_zone_batch_free(malloc_default_zone(), results.data(), count);
- for (void* result : results_copy) {
- ASSERT_GE(batch_frees_intercepted_by_addr[Hash(result)], 1u);
- }
- RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
-}
-
-TEST_F(AllocatorShimTest, InterceptLibcSymbolsFreeDefiniteSize) {
- InsertAllocatorDispatch(&g_mock_dispatch);
-
- void* alloc_ptr = malloc(19);
- ASSERT_NE(nullptr, alloc_ptr);
- ASSERT_GE(allocs_intercepted_by_size[19], 1u);
-
- ChromeMallocZone* default_zone =
- reinterpret_cast<ChromeMallocZone*>(malloc_default_zone());
- default_zone->free_definite_size(malloc_default_zone(), alloc_ptr, 19);
- ASSERT_GE(free_definite_sizes_intercepted_by_size[19], 1u);
- RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
-}
-#endif // defined(OS_MACOSX)
-
-TEST_F(AllocatorShimTest, InterceptCppSymbols) {
- InsertAllocatorDispatch(&g_mock_dispatch);
-
- TestStruct1* new_ptr = new TestStruct1;
- ASSERT_NE(nullptr, new_ptr);
- ASSERT_GE(allocs_intercepted_by_size[sizeof(TestStruct1)], 1u);
-
- TestStruct1* new_array_ptr = new TestStruct1[3];
- ASSERT_NE(nullptr, new_array_ptr);
- ASSERT_GE(allocs_intercepted_by_size[sizeof(TestStruct1) * 3], 1u);
-
- TestStruct2* new_nt_ptr = new (std::nothrow) TestStruct2;
- ASSERT_NE(nullptr, new_nt_ptr);
- ASSERT_GE(allocs_intercepted_by_size[sizeof(TestStruct2)], 1u);
-
- TestStruct2* new_array_nt_ptr = new TestStruct2[3];
- ASSERT_NE(nullptr, new_array_nt_ptr);
- ASSERT_GE(allocs_intercepted_by_size[sizeof(TestStruct2) * 3], 1u);
-
- delete new_ptr;
- ASSERT_GE(frees_intercepted_by_addr[Hash(new_ptr)], 1u);
-
- delete[] new_array_ptr;
- ASSERT_GE(frees_intercepted_by_addr[Hash(new_array_ptr)], 1u);
-
- delete new_nt_ptr;
- ASSERT_GE(frees_intercepted_by_addr[Hash(new_nt_ptr)], 1u);
-
- delete[] new_array_nt_ptr;
- ASSERT_GE(frees_intercepted_by_addr[Hash(new_array_nt_ptr)], 1u);
-
- RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
-}
-
-// This test exercises the case of concurrent OOM failure, which would end up
-// invoking std::new_handler concurrently. This is to cover the CallNewHandler()
-// paths of allocator_shim.cc and smoke-test its thread safey.
-// The test creates kNumThreads threads. Each of them mallocs some memory, and
-// then does a realloc(<new memory>, 0xFEED).
-// The shim intercepts such realloc and makes it fail only once on each thread.
-// We expect to see excactly kNumThreads invocations of the new_handler.
-TEST_F(AllocatorShimTest, NewHandlerConcurrency) {
- const int kNumThreads = 32;
- PlatformThreadHandle threads[kNumThreads];
-
- // The WaitableEvent here is used to attempt to trigger all the threads at
- // the same time, after they have been initialized.
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- ThreadDelegateForNewHandlerTest mock_thread_main(&event);
-
- for (int i = 0; i < kNumThreads; ++i)
- PlatformThread::Create(0, &mock_thread_main, &threads[i]);
-
- std::set_new_handler(&AllocatorShimTest::NewHandler);
- SetCallNewHandlerOnMallocFailure(true); // It's going to fail on realloc().
- InsertAllocatorDispatch(&g_mock_dispatch);
- event.Signal();
- for (int i = 0; i < kNumThreads; ++i)
- PlatformThread::Join(threads[i]);
- RemoveAllocatorDispatchForTesting(&g_mock_dispatch);
- ASSERT_EQ(kNumThreads, GetNumberOfNewHandlerCalls());
-}
-
-} // namespace
-} // namespace allocator
-} // namespace base
diff --git a/base/allocator/malloc_zone_functions_mac_unittest.cc b/base/allocator/malloc_zone_functions_mac_unittest.cc
deleted file mode 100644
index 09aa429..0000000
--- a/base/allocator/malloc_zone_functions_mac_unittest.cc
+++ /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.
-
-#include "base/allocator/malloc_zone_functions_mac.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace allocator {
-
-class MallocZoneFunctionsTest : public testing::Test {
- protected:
- void TearDown() override { ClearAllMallocZonesForTesting(); }
-};
-
-TEST_F(MallocZoneFunctionsTest, TestDefaultZoneMallocFree) {
- ChromeMallocZone* malloc_zone =
- reinterpret_cast<ChromeMallocZone*>(malloc_default_zone());
- StoreMallocZone(malloc_zone);
- int* test = reinterpret_cast<int*>(
- g_malloc_zones[0].malloc(malloc_default_zone(), 33));
- test[0] = 1;
- test[1] = 2;
- g_malloc_zones[0].free(malloc_default_zone(), test);
-}
-
-TEST_F(MallocZoneFunctionsTest, IsZoneAlreadyStored) {
- ChromeMallocZone* malloc_zone =
- reinterpret_cast<ChromeMallocZone*>(malloc_default_zone());
- EXPECT_FALSE(IsMallocZoneAlreadyStored(malloc_zone));
- StoreMallocZone(malloc_zone);
- EXPECT_TRUE(IsMallocZoneAlreadyStored(malloc_zone));
-}
-
-TEST_F(MallocZoneFunctionsTest, CannotDoubleStoreZone) {
- ChromeMallocZone* malloc_zone =
- reinterpret_cast<ChromeMallocZone*>(malloc_default_zone());
- StoreMallocZone(malloc_zone);
- StoreMallocZone(malloc_zone);
- EXPECT_EQ(1, GetMallocZoneCountForTesting());
-}
-
-TEST_F(MallocZoneFunctionsTest, CannotStoreMoreThanMaxZones) {
- std::vector<ChromeMallocZone> zones;
- zones.resize(kMaxZoneCount * 2);
- for (int i = 0; i < kMaxZoneCount * 2; ++i) {
- ChromeMallocZone& zone = zones[i];
- memcpy(&zone, malloc_default_zone(), sizeof(ChromeMallocZone));
- StoreMallocZone(&zone);
- }
-
- int max_zone_count = kMaxZoneCount;
- EXPECT_EQ(max_zone_count, GetMallocZoneCountForTesting());
-}
-
-} // namespace allocator
-} // namespace base
diff --git a/base/allocator/partition_allocator/address_space_randomization_unittest.cc b/base/allocator/partition_allocator/address_space_randomization_unittest.cc
deleted file mode 100644
index a9fe1ce..0000000
--- a/base/allocator/partition_allocator/address_space_randomization_unittest.cc
+++ /dev/null
@@ -1,244 +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/allocator/partition_allocator/address_space_randomization.h"
-
-#include "base/allocator/partition_allocator/page_allocator.h"
-#include "base/bit_cast.h"
-#include "base/bits.h"
-#include "base/sys_info.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include "base/win/windows_version.h"
-// VersionHelpers.h must be included after windows.h.
-#include <VersionHelpers.h>
-#endif
-
-namespace base {
-
-namespace {
-
-uintptr_t GetMask() {
- uintptr_t mask = internal::kASLRMask;
-#if defined(ARCH_CPU_64_BITS)
-// Sanitizers use their own kASLRMask constant.
-#if defined(OS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
- if (!IsWindows8Point1OrGreater()) {
- mask = internal::kASLRMaskBefore8_10;
- }
-#endif // defined(OS_WIN) && !defined(MEMORY_TOOL_REPLACES_ALLOCATOR))
-#elif defined(ARCH_CPU_32_BITS)
-#if defined(OS_WIN)
- BOOL is_wow64 = FALSE;
- if (!IsWow64Process(GetCurrentProcess(), &is_wow64))
- is_wow64 = FALSE;
- if (!is_wow64) {
- mask = 0;
- }
-#endif // defined(OS_WIN)
-#endif // defined(ARCH_CPU_32_BITS)
- return mask;
-}
-
-const size_t kSamples = 100;
-
-uintptr_t GetAddressBits() {
- return reinterpret_cast<uintptr_t>(base::GetRandomPageBase());
-}
-
-uintptr_t GetRandomBits() {
- return GetAddressBits() - internal::kASLROffset;
-}
-
-} // namespace
-
-// Configurations without ASLR are tested here.
-TEST(AddressSpaceRandomizationTest, DisabledASLR) {
- uintptr_t mask = GetMask();
- if (!mask) {
-#if defined(OS_WIN) && defined(ARCH_CPU_32_BITS)
- // ASLR should be turned off on 32-bit Windows.
- EXPECT_EQ(nullptr, base::GetRandomPageBase());
-#else
- // Otherwise, nullptr is very unexpected.
- EXPECT_NE(nullptr, base::GetRandomPageBase());
-#endif
- }
-}
-
-TEST(AddressSpaceRandomizationTest, Alignment) {
- uintptr_t mask = GetMask();
- if (!mask)
- return;
-
- for (size_t i = 0; i < kSamples; ++i) {
- uintptr_t address = GetAddressBits();
- EXPECT_EQ(0ULL, (address & kPageAllocationGranularityOffsetMask));
- }
-}
-
-TEST(AddressSpaceRandomizationTest, Range) {
- uintptr_t mask = GetMask();
- if (!mask)
- return;
-
- uintptr_t min = internal::kASLROffset;
- uintptr_t max = internal::kASLROffset + internal::kASLRMask;
- for (size_t i = 0; i < kSamples; ++i) {
- uintptr_t address = GetAddressBits();
- EXPECT_LE(min, address);
- EXPECT_GE(max + mask, address);
- }
-}
-
-TEST(AddressSpaceRandomizationTest, Predictable) {
- uintptr_t mask = GetMask();
- if (!mask)
- return;
-
- const uintptr_t kInitialSeed = 0xfeed5eedULL;
- base::SetRandomPageBaseSeed(kInitialSeed);
-
- std::vector<uintptr_t> sequence;
- for (size_t i = 0; i < kSamples; ++i) {
- uintptr_t address = reinterpret_cast<uintptr_t>(base::GetRandomPageBase());
- sequence.push_back(address);
- }
-
- base::SetRandomPageBaseSeed(kInitialSeed);
-
- for (size_t i = 0; i < kSamples; ++i) {
- uintptr_t address = reinterpret_cast<uintptr_t>(base::GetRandomPageBase());
- EXPECT_EQ(address, sequence[i]);
- }
-}
-
-// This randomness test is adapted from V8's PRNG tests.
-
-// Chi squared for getting m 0s out of n bits.
-double ChiSquared(int m, int n) {
- double ys_minus_np1 = (m - n / 2.0);
- double chi_squared_1 = ys_minus_np1 * ys_minus_np1 * 2.0 / n;
- double ys_minus_np2 = ((n - m) - n / 2.0);
- double chi_squared_2 = ys_minus_np2 * ys_minus_np2 * 2.0 / n;
- return chi_squared_1 + chi_squared_2;
-}
-
-// Test for correlations between recent bits from the PRNG, or bits that are
-// biased.
-void RandomBitCorrelation(int random_bit) {
- uintptr_t mask = GetMask();
- if ((mask & (1ULL << random_bit)) == 0)
- return; // bit is always 0.
-
-#ifdef DEBUG
- constexpr int kHistory = 2;
- constexpr int kRepeats = 1000;
-#else
- constexpr int kHistory = 8;
- constexpr int kRepeats = 10000;
-#endif
- constexpr int kPointerBits = 8 * sizeof(void*);
- uintptr_t history[kHistory];
- // The predictor bit is either constant 0 or 1, or one of the bits from the
- // history.
- for (int predictor_bit = -2; predictor_bit < kPointerBits; predictor_bit++) {
- // The predicted bit is one of the bits from the PRNG.
- for (int ago = 0; ago < kHistory; ago++) {
- // We don't want to check whether each bit predicts itself.
- if (ago == 0 && predictor_bit == random_bit)
- continue;
-
- // Enter the new random value into the history.
- for (int i = ago; i >= 0; i--) {
- history[i] = GetRandomBits();
- }
-
- // Find out how many of the bits are the same as the prediction bit.
- int m = 0;
- for (int i = 0; i < kRepeats; i++) {
- uintptr_t random = GetRandomBits();
- for (int j = ago - 1; j >= 0; j--)
- history[j + 1] = history[j];
- history[0] = random;
-
- int predicted;
- if (predictor_bit >= 0) {
- predicted = (history[ago] >> predictor_bit) & 1;
- } else {
- predicted = predictor_bit == -2 ? 0 : 1;
- }
- int bit = (random >> random_bit) & 1;
- if (bit == predicted)
- m++;
- }
-
- // Chi squared analysis for k = 2 (2, states: same/not-same) and one
- // degree of freedom (k - 1).
- double chi_squared = ChiSquared(m, kRepeats);
- // For 1 degree of freedom this corresponds to 1 in a million. We are
- // running ~8000 tests, so that would be surprising.
- CHECK_GE(24, chi_squared);
- // If the predictor bit is a fixed 0 or 1 then it makes no sense to
- // repeat the test with a different age.
- if (predictor_bit < 0)
- break;
- }
- }
-}
-
-// Tests are fairly slow, so give each random bit its own test.
-#define TEST_RANDOM_BIT(BIT) \
- TEST(AddressSpaceRandomizationTest, RandomBitCorrelations##BIT) { \
- RandomBitCorrelation(BIT); \
- }
-
-// The first 12 bits on all platforms are always 0.
-TEST_RANDOM_BIT(12)
-TEST_RANDOM_BIT(13)
-TEST_RANDOM_BIT(14)
-TEST_RANDOM_BIT(15)
-TEST_RANDOM_BIT(16)
-TEST_RANDOM_BIT(17)
-TEST_RANDOM_BIT(18)
-TEST_RANDOM_BIT(19)
-TEST_RANDOM_BIT(20)
-TEST_RANDOM_BIT(21)
-TEST_RANDOM_BIT(22)
-TEST_RANDOM_BIT(23)
-TEST_RANDOM_BIT(24)
-TEST_RANDOM_BIT(25)
-TEST_RANDOM_BIT(26)
-TEST_RANDOM_BIT(27)
-TEST_RANDOM_BIT(28)
-TEST_RANDOM_BIT(29)
-TEST_RANDOM_BIT(30)
-TEST_RANDOM_BIT(31)
-#if defined(ARCH_CPU_64_BITS)
-TEST_RANDOM_BIT(32)
-TEST_RANDOM_BIT(33)
-TEST_RANDOM_BIT(34)
-TEST_RANDOM_BIT(35)
-TEST_RANDOM_BIT(36)
-TEST_RANDOM_BIT(37)
-TEST_RANDOM_BIT(38)
-TEST_RANDOM_BIT(39)
-TEST_RANDOM_BIT(40)
-TEST_RANDOM_BIT(41)
-TEST_RANDOM_BIT(42)
-TEST_RANDOM_BIT(43)
-TEST_RANDOM_BIT(44)
-TEST_RANDOM_BIT(45)
-TEST_RANDOM_BIT(46)
-TEST_RANDOM_BIT(47)
-TEST_RANDOM_BIT(48)
-// No platforms have more than 48 address bits.
-#endif // defined(ARCH_CPU_64_BITS)
-
-#undef TEST_RANDOM_BIT
-
-} // namespace base
diff --git a/base/allocator/partition_allocator/page_allocator_unittest.cc b/base/allocator/partition_allocator/page_allocator_unittest.cc
deleted file mode 100644
index ad14c06..0000000
--- a/base/allocator/partition_allocator/page_allocator_unittest.cc
+++ /dev/null
@@ -1,224 +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/allocator/partition_allocator/page_allocator.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include "base/allocator/partition_allocator/address_space_randomization.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
-#include <setjmp.h>
-#include <signal.h>
-#include <sys/mman.h>
-#include <sys/time.h>
-#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA)
-
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-
-namespace base {
-
-namespace {
-
-// Any number of bytes that can be allocated with no trouble.
-constexpr size_t kEasyAllocSize =
- (1024 * 1024) & ~(kPageAllocationGranularity - 1);
-
-// A huge amount of memory, greater than or equal to the ASLR space.
-constexpr size_t kHugeMemoryAmount =
- std::max(internal::kASLRMask, std::size_t{2} * internal::kASLRMask);
-
-} // namespace
-
-TEST(PageAllocatorTest, Rounding) {
- EXPECT_EQ(0u, RoundUpToSystemPage(0u));
- EXPECT_EQ(kSystemPageSize, RoundUpToSystemPage(1));
- EXPECT_EQ(kSystemPageSize, RoundUpToSystemPage(kSystemPageSize - 1));
- EXPECT_EQ(kSystemPageSize, RoundUpToSystemPage(kSystemPageSize));
- EXPECT_EQ(2 * kSystemPageSize, RoundUpToSystemPage(kSystemPageSize + 1));
- EXPECT_EQ(0u, RoundDownToSystemPage(0u));
- EXPECT_EQ(0u, RoundDownToSystemPage(kSystemPageSize - 1));
- EXPECT_EQ(kSystemPageSize, RoundDownToSystemPage(kSystemPageSize));
- EXPECT_EQ(kSystemPageSize, RoundDownToSystemPage(kSystemPageSize + 1));
- EXPECT_EQ(kSystemPageSize, RoundDownToSystemPage(2 * kSystemPageSize - 1));
- EXPECT_EQ(0u, RoundUpToPageAllocationGranularity(0u));
- EXPECT_EQ(kPageAllocationGranularity, RoundUpToPageAllocationGranularity(1));
- EXPECT_EQ(kPageAllocationGranularity,
- RoundUpToPageAllocationGranularity(kPageAllocationGranularity - 1));
- EXPECT_EQ(kPageAllocationGranularity,
- RoundUpToPageAllocationGranularity(kPageAllocationGranularity));
- EXPECT_EQ(2 * kPageAllocationGranularity,
- RoundUpToPageAllocationGranularity(kPageAllocationGranularity + 1));
- EXPECT_EQ(0u, RoundDownToPageAllocationGranularity(0u));
- EXPECT_EQ(
- 0u, RoundDownToPageAllocationGranularity(kPageAllocationGranularity - 1));
- EXPECT_EQ(kPageAllocationGranularity,
- RoundDownToPageAllocationGranularity(kPageAllocationGranularity));
- EXPECT_EQ(kPageAllocationGranularity, RoundDownToPageAllocationGranularity(
- kPageAllocationGranularity + 1));
- EXPECT_EQ(
- kPageAllocationGranularity,
- RoundDownToPageAllocationGranularity(2 * kPageAllocationGranularity - 1));
-}
-
-// Test that failed page allocations invoke base::ReleaseReservation().
-// We detect this by making a reservation and ensuring that after failure, we
-// can make a new reservation.
-TEST(PageAllocatorTest, AllocFailure) {
- // Release any reservation made by another test.
- ReleaseReservation();
-
- // We can make a reservation.
- EXPECT_TRUE(ReserveAddressSpace(kEasyAllocSize));
-
- // We can't make another reservation until we trigger an allocation failure.
- EXPECT_FALSE(ReserveAddressSpace(kEasyAllocSize));
-
- size_t size = kHugeMemoryAmount;
- // Skip the test for sanitizers and platforms with ASLR turned off.
- if (size == 0)
- return;
-
- void* result = AllocPages(nullptr, size, kPageAllocationGranularity,
- PageInaccessible, PageTag::kChromium, false);
- if (result == nullptr) {
- // We triggered allocation failure. Our reservation should have been
- // released, and we should be able to make a new reservation.
- EXPECT_TRUE(ReserveAddressSpace(kEasyAllocSize));
- ReleaseReservation();
- return;
- }
- // We couldn't fail. Make sure reservation is still there.
- EXPECT_FALSE(ReserveAddressSpace(kEasyAllocSize));
-}
-
-// TODO(crbug.com/765801): Test failed on chromium.win/Win10 Tests x64.
-#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
-#define MAYBE_ReserveAddressSpace DISABLED_ReserveAddressSpace
-#else
-#define MAYBE_ReserveAddressSpace ReserveAddressSpace
-#endif // defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
-
-// Test that reserving address space can fail.
-TEST(PageAllocatorTest, MAYBE_ReserveAddressSpace) {
- // Release any reservation made by another test.
- ReleaseReservation();
-
- size_t size = kHugeMemoryAmount;
- // Skip the test for sanitizers and platforms with ASLR turned off.
- if (size == 0)
- return;
-
- bool success = ReserveAddressSpace(size);
- if (!success) {
- EXPECT_TRUE(ReserveAddressSpace(kEasyAllocSize));
- return;
- }
- // We couldn't fail. Make sure reservation is still there.
- EXPECT_FALSE(ReserveAddressSpace(kEasyAllocSize));
-}
-
-TEST(PageAllocatorTest, AllocAndFreePages) {
- void* buffer = AllocPages(nullptr, kPageAllocationGranularity,
- kPageAllocationGranularity, PageReadWrite,
- PageTag::kChromium, true);
- EXPECT_TRUE(buffer);
- int* buffer0 = reinterpret_cast<int*>(buffer);
- *buffer0 = 42;
- EXPECT_EQ(42, *buffer0);
- FreePages(buffer, kPageAllocationGranularity);
-}
-
-// Test permission setting on POSIX, where we can set a trap handler.
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
-
-namespace {
-sigjmp_buf g_continuation;
-
-void SignalHandler(int signal, siginfo_t* info, void*) {
- siglongjmp(g_continuation, 1);
-}
-} // namespace
-
-// On Mac, sometimes we get SIGBUS instead of SIGSEGV, so handle that too.
-#if defined(OS_MACOSX)
-#define EXTRA_FAULT_BEGIN_ACTION() \
- struct sigaction old_bus_action; \
- sigaction(SIGBUS, &action, &old_bus_action);
-#define EXTRA_FAULT_END_ACTION() sigaction(SIGBUS, &old_bus_action, nullptr);
-#else
-#define EXTRA_FAULT_BEGIN_ACTION()
-#define EXTRA_FAULT_END_ACTION()
-#endif
-
-// Install a signal handler so we can catch the fault we're about to trigger.
-#define FAULT_TEST_BEGIN() \
- struct sigaction action = {}; \
- struct sigaction old_action = {}; \
- action.sa_sigaction = SignalHandler; \
- sigemptyset(&action.sa_mask); \
- action.sa_flags = SA_SIGINFO; \
- sigaction(SIGSEGV, &action, &old_action); \
- EXTRA_FAULT_BEGIN_ACTION(); \
- int const save_sigs = 1; \
- if (!sigsetjmp(g_continuation, save_sigs)) {
-// Fault generating code goes here...
-
-// Handle when sigsetjmp returns nonzero (we are returning from our handler).
-#define FAULT_TEST_END() \
- } \
- else { \
- sigaction(SIGSEGV, &old_action, nullptr); \
- EXTRA_FAULT_END_ACTION(); \
- }
-
-TEST(PageAllocatorTest, InaccessiblePages) {
- void* buffer = AllocPages(nullptr, kPageAllocationGranularity,
- kPageAllocationGranularity, PageInaccessible,
- PageTag::kChromium, true);
- EXPECT_TRUE(buffer);
-
- FAULT_TEST_BEGIN();
-
- // Reading from buffer should fault.
- int* buffer0 = reinterpret_cast<int*>(buffer);
- int buffer0_contents = *buffer0;
- EXPECT_EQ(buffer0_contents, *buffer0);
- EXPECT_TRUE(false);
-
- FAULT_TEST_END();
-
- FreePages(buffer, kPageAllocationGranularity);
-}
-
-TEST(PageAllocatorTest, ReadExecutePages) {
- void* buffer = AllocPages(nullptr, kPageAllocationGranularity,
- kPageAllocationGranularity, PageReadExecute,
- PageTag::kChromium, true);
- EXPECT_TRUE(buffer);
- int* buffer0 = reinterpret_cast<int*>(buffer);
- // Reading from buffer should succeed.
- int buffer0_contents = *buffer0;
-
- FAULT_TEST_BEGIN();
-
- // Writing to buffer should fault.
- *buffer0 = ~buffer0_contents;
- EXPECT_TRUE(false);
-
- FAULT_TEST_END();
-
- // Make sure no write occurred.
- EXPECT_EQ(buffer0_contents, *buffer0);
- FreePages(buffer, kPageAllocationGranularity);
-}
-
-#endif // defined(OS_POSIX) && !defined(OS_FUCHSIA)
-
-} // namespace base
-
-#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/base/allocator/partition_allocator/partition_alloc_unittest.cc b/base/allocator/partition_allocator/partition_alloc_unittest.cc
deleted file mode 100644
index 994f339..0000000
--- a/base/allocator/partition_allocator/partition_alloc_unittest.cc
+++ /dev/null
@@ -1,2129 +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/allocator/partition_allocator/partition_alloc.h"
-
-#include <stdlib.h>
-#include <string.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/allocator/partition_allocator/address_space_randomization.h"
-#include "base/bit_cast.h"
-#include "base/bits.h"
-#include "base/sys_info.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <sys/mman.h>
-#if !defined(OS_FUCHSIA)
-#include <sys/resource.h>
-#endif
-#include <sys/time.h>
-#endif // defined(OS_POSIX)
-
-#if !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
-
-// Because there is so much deep inspection of the internal objects,
-// explicitly annotating the namespaces for commonly expected objects makes the
-// code unreadable. Prefer using directives instead.
-using base::internal::PartitionBucket;
-using base::internal::PartitionPage;
-
-namespace {
-
-constexpr size_t kTestMaxAllocation = base::kSystemPageSize;
-
-bool IsLargeMemoryDevice() {
- // Treat any device with 2GiB or more of physical memory as a "large memory
- // device". We check for slightly less than 2GiB so that devices with a small
- // amount of memory not accessible to the OS still count as "large".
- return base::SysInfo::AmountOfPhysicalMemory() >= 2040LL * 1024 * 1024;
-}
-
-bool SetAddressSpaceLimit() {
-#if !defined(ARCH_CPU_64_BITS) || !defined(OS_POSIX)
- // 32 bits => address space is limited already.
- return true;
-#elif defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
- // macOS will accept, but not enforce, |RLIMIT_AS| changes. See
- // https://crbug.com/435269 and rdar://17576114.
- //
- // Note: This number must be not less than 6 GB, because with
- // sanitizer_coverage_flags=edge, it reserves > 5 GB of address space. See
- // https://crbug.com/674665.
- const size_t kAddressSpaceLimit = static_cast<size_t>(6144) * 1024 * 1024;
- struct rlimit limit;
- if (getrlimit(RLIMIT_AS, &limit) != 0)
- return false;
- if (limit.rlim_cur == RLIM_INFINITY || limit.rlim_cur > kAddressSpaceLimit) {
- limit.rlim_cur = kAddressSpaceLimit;
- if (setrlimit(RLIMIT_AS, &limit) != 0)
- return false;
- }
- return true;
-#else
- return false;
-#endif
-}
-
-bool ClearAddressSpaceLimit() {
-#if !defined(ARCH_CPU_64_BITS) || !defined(OS_POSIX) || defined(OS_FUCHSIA)
- return true;
-#elif defined(OS_POSIX)
- struct rlimit limit;
- if (getrlimit(RLIMIT_AS, &limit) != 0)
- return false;
- limit.rlim_cur = limit.rlim_max;
- if (setrlimit(RLIMIT_AS, &limit) != 0)
- return false;
- return true;
-#else
- return false;
-#endif
-}
-
-} // namespace
-
-namespace base {
-
-// NOTE: Though this test actually excercises interfaces inside the ::base
-// namespace, the unittest is inside the ::base::internal spaces because a
-// portion of the test expectations require inspecting objects and behavior
-// in the ::base::internal namespace. An alternate formulation would be to
-// explicitly add using statements for each inspected type but this felt more
-// readable.
-namespace internal {
-
-const size_t kTestAllocSize = 16;
-#if !DCHECK_IS_ON()
-const size_t kPointerOffset = 0;
-const size_t kExtraAllocSize = 0;
-#else
-const size_t kPointerOffset = kCookieSize;
-const size_t kExtraAllocSize = kCookieSize * 2;
-#endif
-const size_t kRealAllocSize = kTestAllocSize + kExtraAllocSize;
-const size_t kTestBucketIndex = kRealAllocSize >> kBucketShift;
-
-const char* type_name = nullptr;
-
-class PartitionAllocTest : public testing::Test {
- protected:
- PartitionAllocTest() = default;
-
- ~PartitionAllocTest() override = default;
-
- void SetUp() override {
- allocator.init();
- generic_allocator.init();
- }
-
- PartitionPage* GetFullPage(size_t size) {
- size_t real_size = size + kExtraAllocSize;
- size_t bucket_index = real_size >> kBucketShift;
- PartitionBucket* bucket = &allocator.root()->buckets()[bucket_index];
- size_t num_slots =
- (bucket->num_system_pages_per_slot_span * kSystemPageSize) / real_size;
- void* first = nullptr;
- void* last = nullptr;
- size_t i;
- for (i = 0; i < num_slots; ++i) {
- void* ptr = allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr);
- if (!i)
- first = PartitionCookieFreePointerAdjust(ptr);
- else if (i == num_slots - 1)
- last = PartitionCookieFreePointerAdjust(ptr);
- }
- EXPECT_EQ(PartitionPage::FromPointer(first),
- PartitionPage::FromPointer(last));
- if (bucket->num_system_pages_per_slot_span ==
- kNumSystemPagesPerPartitionPage)
- EXPECT_EQ(reinterpret_cast<size_t>(first) & kPartitionPageBaseMask,
- reinterpret_cast<size_t>(last) & kPartitionPageBaseMask);
- EXPECT_EQ(num_slots, static_cast<size_t>(
- bucket->active_pages_head->num_allocated_slots));
- EXPECT_EQ(nullptr, bucket->active_pages_head->freelist_head);
- EXPECT_TRUE(bucket->active_pages_head);
- EXPECT_TRUE(bucket->active_pages_head !=
- PartitionPage::get_sentinel_page());
- return bucket->active_pages_head;
- }
-
- void CycleFreeCache(size_t size) {
- size_t real_size = size + kExtraAllocSize;
- size_t bucket_index = real_size >> kBucketShift;
- PartitionBucket* bucket = &allocator.root()->buckets()[bucket_index];
- DCHECK(!bucket->active_pages_head->num_allocated_slots);
-
- for (size_t i = 0; i < kMaxFreeableSpans; ++i) {
- void* ptr = allocator.root()->Alloc(size, type_name);
- EXPECT_EQ(1, bucket->active_pages_head->num_allocated_slots);
- PartitionFree(ptr);
- EXPECT_EQ(0, bucket->active_pages_head->num_allocated_slots);
- EXPECT_NE(-1, bucket->active_pages_head->empty_cache_index);
- }
- }
-
- void CycleGenericFreeCache(size_t size) {
- for (size_t i = 0; i < kMaxFreeableSpans; ++i) {
- void* ptr = generic_allocator.root()->Alloc(size, type_name);
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- PartitionBucket* bucket = page->bucket;
- EXPECT_EQ(1, bucket->active_pages_head->num_allocated_slots);
- generic_allocator.root()->Free(ptr);
- EXPECT_EQ(0, bucket->active_pages_head->num_allocated_slots);
- EXPECT_NE(-1, bucket->active_pages_head->empty_cache_index);
- }
- }
-
- void DoReturnNullTest(size_t allocSize, bool use_realloc) {
- // TODO(crbug.com/678782): Where necessary and possible, disable the
- // platform's OOM-killing behavior. OOM-killing makes this test flaky on
- // low-memory devices.
- if (!IsLargeMemoryDevice()) {
- LOG(WARNING)
- << "Skipping test on this device because of crbug.com/678782";
- return;
- }
-
- ASSERT_TRUE(SetAddressSpaceLimit());
-
- // Work out the number of allocations for 6 GB of memory.
- const int numAllocations = (6 * 1024 * 1024) / (allocSize / 1024);
-
- void** ptrs = reinterpret_cast<void**>(generic_allocator.root()->Alloc(
- numAllocations * sizeof(void*), type_name));
- int i;
-
- for (i = 0; i < numAllocations; ++i) {
- if (use_realloc) {
- ptrs[i] = PartitionAllocGenericFlags(
- generic_allocator.root(), PartitionAllocReturnNull, 1, type_name);
- ptrs[i] = PartitionReallocGenericFlags(generic_allocator.root(),
- PartitionAllocReturnNull,
- ptrs[i], allocSize, type_name);
- } else {
- ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
- PartitionAllocReturnNull,
- allocSize, type_name);
- }
- if (!i)
- EXPECT_TRUE(ptrs[0]);
- if (!ptrs[i]) {
- ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
- PartitionAllocReturnNull,
- allocSize, type_name);
- EXPECT_FALSE(ptrs[i]);
- break;
- }
- }
-
- // We shouldn't succeed in allocating all 6 GB of memory. If we do, then
- // we're not actually testing anything here.
- EXPECT_LT(i, numAllocations);
-
- // Free, reallocate and free again each block we allocated. We do this to
- // check that freeing memory also works correctly after a failed allocation.
- for (--i; i >= 0; --i) {
- generic_allocator.root()->Free(ptrs[i]);
- ptrs[i] = PartitionAllocGenericFlags(generic_allocator.root(),
- PartitionAllocReturnNull, allocSize,
- type_name);
- EXPECT_TRUE(ptrs[i]);
- generic_allocator.root()->Free(ptrs[i]);
- }
-
- generic_allocator.root()->Free(ptrs);
-
- EXPECT_TRUE(ClearAddressSpaceLimit());
- }
-
- SizeSpecificPartitionAllocator<kTestMaxAllocation> allocator;
- PartitionAllocatorGeneric generic_allocator;
-};
-
-class PartitionAllocDeathTest : public PartitionAllocTest {};
-
-namespace {
-
-void FreeFullPage(PartitionPage* page) {
- size_t size = page->bucket->slot_size;
- size_t num_slots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) / size;
- EXPECT_EQ(num_slots, static_cast<size_t>(abs(page->num_allocated_slots)));
- char* ptr = reinterpret_cast<char*>(PartitionPage::ToPointer(page));
- size_t i;
- for (i = 0; i < num_slots; ++i) {
- PartitionFree(ptr + kPointerOffset);
- ptr += size;
- }
-}
-
-#if defined(OS_LINUX)
-bool CheckPageInCore(void* ptr, bool in_core) {
- unsigned char ret = 0;
- EXPECT_EQ(0, mincore(ptr, kSystemPageSize, &ret));
- return in_core == (ret & 1);
-}
-
-#define CHECK_PAGE_IN_CORE(ptr, in_core) \
- EXPECT_TRUE(CheckPageInCore(ptr, in_core))
-#else
-#define CHECK_PAGE_IN_CORE(ptr, in_core) (void)(0)
-#endif // defined(OS_LINUX)
-
-class MockPartitionStatsDumper : public PartitionStatsDumper {
- public:
- MockPartitionStatsDumper()
- : total_resident_bytes(0),
- total_active_bytes(0),
- total_decommittable_bytes(0),
- total_discardable_bytes(0) {}
-
- void PartitionDumpTotals(const char* partition_name,
- const PartitionMemoryStats* stats) override {
- EXPECT_GE(stats->total_mmapped_bytes, stats->total_resident_bytes);
- EXPECT_EQ(total_resident_bytes, stats->total_resident_bytes);
- EXPECT_EQ(total_active_bytes, stats->total_active_bytes);
- EXPECT_EQ(total_decommittable_bytes, stats->total_decommittable_bytes);
- EXPECT_EQ(total_discardable_bytes, stats->total_discardable_bytes);
- }
-
- void PartitionsDumpBucketStats(
- const char* partition_name,
- const PartitionBucketMemoryStats* stats) override {
- (void)partition_name;
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->bucket_slot_size & kAllocationGranularityMask);
- bucket_stats.push_back(*stats);
- total_resident_bytes += stats->resident_bytes;
- total_active_bytes += stats->active_bytes;
- total_decommittable_bytes += stats->decommittable_bytes;
- total_discardable_bytes += stats->discardable_bytes;
- }
-
- bool IsMemoryAllocationRecorded() {
- return total_resident_bytes != 0 && total_active_bytes != 0;
- }
-
- const PartitionBucketMemoryStats* GetBucketStats(size_t bucket_size) {
- for (size_t i = 0; i < bucket_stats.size(); ++i) {
- if (bucket_stats[i].bucket_slot_size == bucket_size)
- return &bucket_stats[i];
- }
- return nullptr;
- }
-
- private:
- size_t total_resident_bytes;
- size_t total_active_bytes;
- size_t total_decommittable_bytes;
- size_t total_discardable_bytes;
-
- std::vector<PartitionBucketMemoryStats> bucket_stats;
-};
-
-} // namespace
-
-// Check that the most basic of allocate / free pairs work.
-TEST_F(PartitionAllocTest, Basic) {
- PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
- PartitionPage* seedPage = PartitionPage::get_sentinel_page();
-
- EXPECT_FALSE(bucket->empty_pages_head);
- EXPECT_FALSE(bucket->decommitted_pages_head);
- EXPECT_EQ(seedPage, bucket->active_pages_head);
- EXPECT_EQ(nullptr, bucket->active_pages_head->next_page);
-
- void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_TRUE(ptr);
- EXPECT_EQ(kPointerOffset,
- reinterpret_cast<size_t>(ptr) & kPartitionPageOffsetMask);
- // Check that the offset appears to include a guard page.
- EXPECT_EQ(kPartitionPageSize + kPointerOffset,
- reinterpret_cast<size_t>(ptr) & kSuperPageOffsetMask);
-
- PartitionFree(ptr);
- // Expect that the last active page gets noticed as empty but doesn't get
- // decommitted.
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_FALSE(bucket->decommitted_pages_head);
-}
-
-// Test multiple allocations, and freelist handling.
-TEST_F(PartitionAllocTest, MultiAlloc) {
- char* ptr1 = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- char* ptr2 = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- EXPECT_TRUE(ptr1);
- EXPECT_TRUE(ptr2);
- ptrdiff_t diff = ptr2 - ptr1;
- EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff);
-
- // Check that we re-use the just-freed slot.
- PartitionFree(ptr2);
- ptr2 = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- EXPECT_TRUE(ptr2);
- diff = ptr2 - ptr1;
- EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff);
- PartitionFree(ptr1);
- ptr1 = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- EXPECT_TRUE(ptr1);
- diff = ptr2 - ptr1;
- EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize), diff);
-
- char* ptr3 = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- EXPECT_TRUE(ptr3);
- diff = ptr3 - ptr1;
- EXPECT_EQ(static_cast<ptrdiff_t>(kRealAllocSize * 2), diff);
-
- PartitionFree(ptr1);
- PartitionFree(ptr2);
- PartitionFree(ptr3);
-}
-
-// Test a bucket with multiple pages.
-TEST_F(PartitionAllocTest, MultiPages) {
- PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
-
- PartitionPage* page = GetFullPage(kTestAllocSize);
- FreeFullPage(page);
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
- EXPECT_EQ(nullptr, page->next_page);
- EXPECT_EQ(0, page->num_allocated_slots);
-
- page = GetFullPage(kTestAllocSize);
- PartitionPage* page2 = GetFullPage(kTestAllocSize);
-
- EXPECT_EQ(page2, bucket->active_pages_head);
- EXPECT_EQ(nullptr, page2->next_page);
- EXPECT_EQ(reinterpret_cast<uintptr_t>(PartitionPage::ToPointer(page)) &
- kSuperPageBaseMask,
- reinterpret_cast<uintptr_t>(PartitionPage::ToPointer(page2)) &
- kSuperPageBaseMask);
-
- // Fully free the non-current page. This will leave us with no current
- // active page because one is empty and the other is full.
- FreeFullPage(page);
- EXPECT_EQ(0, page->num_allocated_slots);
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
-
- // Allocate a new page, it should pull from the freelist.
- page = GetFullPage(kTestAllocSize);
- EXPECT_FALSE(bucket->empty_pages_head);
- EXPECT_EQ(page, bucket->active_pages_head);
-
- FreeFullPage(page);
- FreeFullPage(page2);
- EXPECT_EQ(0, page->num_allocated_slots);
- EXPECT_EQ(0, page2->num_allocated_slots);
- EXPECT_EQ(0, page2->num_unprovisioned_slots);
- EXPECT_NE(-1, page2->empty_cache_index);
-}
-
-// Test some finer aspects of internal page transitions.
-TEST_F(PartitionAllocTest, PageTransitions) {
- PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
-
- PartitionPage* page1 = GetFullPage(kTestAllocSize);
- EXPECT_EQ(page1, bucket->active_pages_head);
- EXPECT_EQ(nullptr, page1->next_page);
- PartitionPage* page2 = GetFullPage(kTestAllocSize);
- EXPECT_EQ(page2, bucket->active_pages_head);
- EXPECT_EQ(nullptr, page2->next_page);
-
- // Bounce page1 back into the non-full list then fill it up again.
- char* ptr =
- reinterpret_cast<char*>(PartitionPage::ToPointer(page1)) + kPointerOffset;
- PartitionFree(ptr);
- EXPECT_EQ(page1, bucket->active_pages_head);
- (void)allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_EQ(page1, bucket->active_pages_head);
- EXPECT_EQ(page2, bucket->active_pages_head->next_page);
-
- // Allocating another page at this point should cause us to scan over page1
- // (which is both full and NOT our current page), and evict it from the
- // freelist. Older code had a O(n^2) condition due to failure to do this.
- PartitionPage* page3 = GetFullPage(kTestAllocSize);
- EXPECT_EQ(page3, bucket->active_pages_head);
- EXPECT_EQ(nullptr, page3->next_page);
-
- // Work out a pointer into page2 and free it.
- ptr =
- reinterpret_cast<char*>(PartitionPage::ToPointer(page2)) + kPointerOffset;
- PartitionFree(ptr);
- // Trying to allocate at this time should cause us to cycle around to page2
- // and find the recently freed slot.
- char* newPtr = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- EXPECT_EQ(ptr, newPtr);
- EXPECT_EQ(page2, bucket->active_pages_head);
- EXPECT_EQ(page3, page2->next_page);
-
- // Work out a pointer into page1 and free it. This should pull the page
- // back into the list of available pages.
- ptr =
- reinterpret_cast<char*>(PartitionPage::ToPointer(page1)) + kPointerOffset;
- PartitionFree(ptr);
- // This allocation should be satisfied by page1.
- newPtr = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- EXPECT_EQ(ptr, newPtr);
- EXPECT_EQ(page1, bucket->active_pages_head);
- EXPECT_EQ(page2, page1->next_page);
-
- FreeFullPage(page3);
- FreeFullPage(page2);
- FreeFullPage(page1);
-
- // Allocating whilst in this state exposed a bug, so keep the test.
- ptr = reinterpret_cast<char*>(
- allocator.root()->Alloc(kTestAllocSize, type_name));
- PartitionFree(ptr);
-}
-
-// Test some corner cases relating to page transitions in the internal
-// free page list metadata bucket.
-TEST_F(PartitionAllocTest, FreePageListPageTransitions) {
- PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
-
- size_t numToFillFreeListPage =
- kPartitionPageSize / (sizeof(PartitionPage) + kExtraAllocSize);
- // The +1 is because we need to account for the fact that the current page
- // never gets thrown on the freelist.
- ++numToFillFreeListPage;
- auto pages = std::make_unique<PartitionPage* []>(numToFillFreeListPage);
-
- size_t i;
- for (i = 0; i < numToFillFreeListPage; ++i) {
- pages[i] = GetFullPage(kTestAllocSize);
- }
- EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->active_pages_head);
- for (i = 0; i < numToFillFreeListPage; ++i)
- FreeFullPage(pages[i]);
- EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
- EXPECT_TRUE(bucket->empty_pages_head);
-
- // Allocate / free in a different bucket size so we get control of a
- // different free page list. We need two pages because one will be the last
- // active page and not get freed.
- PartitionPage* page1 = GetFullPage(kTestAllocSize * 2);
- PartitionPage* page2 = GetFullPage(kTestAllocSize * 2);
- FreeFullPage(page1);
- FreeFullPage(page2);
-
- for (i = 0; i < numToFillFreeListPage; ++i) {
- pages[i] = GetFullPage(kTestAllocSize);
- }
- EXPECT_EQ(pages[numToFillFreeListPage - 1], bucket->active_pages_head);
-
- for (i = 0; i < numToFillFreeListPage; ++i)
- FreeFullPage(pages[i]);
- EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
- EXPECT_TRUE(bucket->empty_pages_head);
-}
-
-// Test a large series of allocations that cross more than one underlying
-// 64KB super page allocation.
-TEST_F(PartitionAllocTest, MultiPageAllocs) {
- // This is guaranteed to cross a super page boundary because the first
- // partition page "slot" will be taken up by a guard page.
- size_t numPagesNeeded = kNumPartitionPagesPerSuperPage;
- // The super page should begin and end in a guard so we one less page in
- // order to allocate a single page in the new super page.
- --numPagesNeeded;
-
- EXPECT_GT(numPagesNeeded, 1u);
- auto pages = std::make_unique<PartitionPage* []>(numPagesNeeded);
- uintptr_t firstSuperPageBase = 0;
- size_t i;
- for (i = 0; i < numPagesNeeded; ++i) {
- pages[i] = GetFullPage(kTestAllocSize);
- void* storagePtr = PartitionPage::ToPointer(pages[i]);
- if (!i)
- firstSuperPageBase =
- reinterpret_cast<uintptr_t>(storagePtr) & kSuperPageBaseMask;
- if (i == numPagesNeeded - 1) {
- uintptr_t secondSuperPageBase =
- reinterpret_cast<uintptr_t>(storagePtr) & kSuperPageBaseMask;
- uintptr_t secondSuperPageOffset =
- reinterpret_cast<uintptr_t>(storagePtr) & kSuperPageOffsetMask;
- EXPECT_FALSE(secondSuperPageBase == firstSuperPageBase);
- // Check that we allocated a guard page for the second page.
- EXPECT_EQ(kPartitionPageSize, secondSuperPageOffset);
- }
- }
- for (i = 0; i < numPagesNeeded; ++i)
- FreeFullPage(pages[i]);
-}
-
-// Test the generic allocation functions that can handle arbitrary sizes and
-// reallocing etc.
-TEST_F(PartitionAllocTest, GenericAlloc) {
- void* ptr = generic_allocator.root()->Alloc(1, type_name);
- EXPECT_TRUE(ptr);
- generic_allocator.root()->Free(ptr);
- ptr = generic_allocator.root()->Alloc(kGenericMaxBucketed + 1, type_name);
- EXPECT_TRUE(ptr);
- generic_allocator.root()->Free(ptr);
-
- ptr = generic_allocator.root()->Alloc(1, type_name);
- EXPECT_TRUE(ptr);
- void* origPtr = ptr;
- char* charPtr = static_cast<char*>(ptr);
- *charPtr = 'A';
-
- // Change the size of the realloc, remaining inside the same bucket.
- void* newPtr = generic_allocator.root()->Realloc(ptr, 2, type_name);
- EXPECT_EQ(ptr, newPtr);
- newPtr = generic_allocator.root()->Realloc(ptr, 1, type_name);
- EXPECT_EQ(ptr, newPtr);
- newPtr =
- generic_allocator.root()->Realloc(ptr, kGenericSmallestBucket, type_name);
- EXPECT_EQ(ptr, newPtr);
-
- // Change the size of the realloc, switching buckets.
- newPtr = generic_allocator.root()->Realloc(ptr, kGenericSmallestBucket + 1,
- type_name);
- EXPECT_NE(newPtr, ptr);
- // Check that the realloc copied correctly.
- char* newCharPtr = static_cast<char*>(newPtr);
- EXPECT_EQ(*newCharPtr, 'A');
-#if DCHECK_IS_ON()
- // Subtle: this checks for an old bug where we copied too much from the
- // source of the realloc. The condition can be detected by a trashing of
- // the uninitialized value in the space of the upsized allocation.
- EXPECT_EQ(kUninitializedByte,
- static_cast<unsigned char>(*(newCharPtr + kGenericSmallestBucket)));
-#endif
- *newCharPtr = 'B';
- // The realloc moved. To check that the old allocation was freed, we can
- // do an alloc of the old allocation size and check that the old allocation
- // address is at the head of the freelist and reused.
- void* reusedPtr = generic_allocator.root()->Alloc(1, type_name);
- EXPECT_EQ(reusedPtr, origPtr);
- generic_allocator.root()->Free(reusedPtr);
-
- // Downsize the realloc.
- ptr = newPtr;
- newPtr = generic_allocator.root()->Realloc(ptr, 1, type_name);
- EXPECT_EQ(newPtr, origPtr);
- newCharPtr = static_cast<char*>(newPtr);
- EXPECT_EQ(*newCharPtr, 'B');
- *newCharPtr = 'C';
-
- // Upsize the realloc to outside the partition.
- ptr = newPtr;
- newPtr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed + 1,
- type_name);
- EXPECT_NE(newPtr, ptr);
- newCharPtr = static_cast<char*>(newPtr);
- EXPECT_EQ(*newCharPtr, 'C');
- *newCharPtr = 'D';
-
- // Upsize and downsize the realloc, remaining outside the partition.
- ptr = newPtr;
- newPtr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed * 10,
- type_name);
- newCharPtr = static_cast<char*>(newPtr);
- EXPECT_EQ(*newCharPtr, 'D');
- *newCharPtr = 'E';
- ptr = newPtr;
- newPtr = generic_allocator.root()->Realloc(ptr, kGenericMaxBucketed * 2,
- type_name);
- newCharPtr = static_cast<char*>(newPtr);
- EXPECT_EQ(*newCharPtr, 'E');
- *newCharPtr = 'F';
-
- // Downsize the realloc to inside the partition.
- ptr = newPtr;
- newPtr = generic_allocator.root()->Realloc(ptr, 1, type_name);
- EXPECT_NE(newPtr, ptr);
- EXPECT_EQ(newPtr, origPtr);
- newCharPtr = static_cast<char*>(newPtr);
- EXPECT_EQ(*newCharPtr, 'F');
-
- generic_allocator.root()->Free(newPtr);
-}
-
-// Test the generic allocation functions can handle some specific sizes of
-// interest.
-TEST_F(PartitionAllocTest, GenericAllocSizes) {
- void* ptr = generic_allocator.root()->Alloc(0, type_name);
- EXPECT_TRUE(ptr);
- generic_allocator.root()->Free(ptr);
-
- // kPartitionPageSize is interesting because it results in just one
- // allocation per page, which tripped up some corner cases.
- size_t size = kPartitionPageSize - kExtraAllocSize;
- ptr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr);
- void* ptr2 = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr2);
- generic_allocator.root()->Free(ptr);
- // Should be freeable at this point.
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_NE(-1, page->empty_cache_index);
- generic_allocator.root()->Free(ptr2);
-
- size = (((kPartitionPageSize * kMaxPartitionPagesPerSlotSpan) -
- kSystemPageSize) /
- 2) -
- kExtraAllocSize;
- ptr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr);
- memset(ptr, 'A', size);
- ptr2 = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr2);
- void* ptr3 = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr3);
- void* ptr4 = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr4);
-
- page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- PartitionPage* page2 =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr3));
- EXPECT_NE(page, page2);
-
- generic_allocator.root()->Free(ptr);
- generic_allocator.root()->Free(ptr3);
- generic_allocator.root()->Free(ptr2);
- // Should be freeable at this point.
- EXPECT_NE(-1, page->empty_cache_index);
- EXPECT_EQ(0, page->num_allocated_slots);
- EXPECT_EQ(0, page->num_unprovisioned_slots);
- void* newPtr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_EQ(ptr3, newPtr);
- newPtr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_EQ(ptr2, newPtr);
-#if defined(OS_LINUX) && !DCHECK_IS_ON()
- // On Linux, we have a guarantee that freelisting a page should cause its
- // contents to be nulled out. We check for null here to detect an bug we
- // had where a large slot size was causing us to not properly free all
- // resources back to the system.
- // We only run the check when asserts are disabled because when they are
- // enabled, the allocated area is overwritten with an "uninitialized"
- // byte pattern.
- EXPECT_EQ(0, *(reinterpret_cast<char*>(newPtr) + (size - 1)));
-#endif
- generic_allocator.root()->Free(newPtr);
- generic_allocator.root()->Free(ptr3);
- generic_allocator.root()->Free(ptr4);
-
- // Can we allocate a massive (512MB) size?
- // Allocate 512MB, but +1, to test for cookie writing alignment issues.
- // Test this only if the device has enough memory or it might fail due
- // to OOM.
- if (IsLargeMemoryDevice()) {
- ptr = generic_allocator.root()->Alloc(512 * 1024 * 1024 + 1, type_name);
- generic_allocator.root()->Free(ptr);
- }
-
- // Check a more reasonable, but still direct mapped, size.
- // Chop a system page and a byte off to test for rounding errors.
- size = 20 * 1024 * 1024;
- size -= kSystemPageSize;
- size -= 1;
- ptr = generic_allocator.root()->Alloc(size, type_name);
- char* charPtr = reinterpret_cast<char*>(ptr);
- *(charPtr + (size - 1)) = 'A';
- generic_allocator.root()->Free(ptr);
-
- // Can we free null?
- generic_allocator.root()->Free(nullptr);
-
- // Do we correctly get a null for a failed allocation?
- EXPECT_EQ(nullptr, PartitionAllocGenericFlags(
- generic_allocator.root(), PartitionAllocReturnNull,
- 3u * 1024 * 1024 * 1024, type_name));
-}
-
-// Test that we can fetch the real allocated size after an allocation.
-TEST_F(PartitionAllocTest, GenericAllocGetSize) {
- void* ptr;
- size_t requested_size, actual_size, predicted_size;
-
- EXPECT_TRUE(PartitionAllocSupportsGetSize());
-
- // Allocate something small.
- requested_size = 511 - kExtraAllocSize;
- predicted_size = generic_allocator.root()->ActualSize(requested_size);
- ptr = generic_allocator.root()->Alloc(requested_size, type_name);
- EXPECT_TRUE(ptr);
- actual_size = PartitionAllocGetSize(ptr);
- EXPECT_EQ(predicted_size, actual_size);
- EXPECT_LT(requested_size, actual_size);
- generic_allocator.root()->Free(ptr);
-
- // Allocate a size that should be a perfect match for a bucket, because it
- // is an exact power of 2.
- requested_size = (256 * 1024) - kExtraAllocSize;
- predicted_size = generic_allocator.root()->ActualSize(requested_size);
- ptr = generic_allocator.root()->Alloc(requested_size, type_name);
- EXPECT_TRUE(ptr);
- actual_size = PartitionAllocGetSize(ptr);
- EXPECT_EQ(predicted_size, actual_size);
- EXPECT_EQ(requested_size, actual_size);
- generic_allocator.root()->Free(ptr);
-
- // Allocate a size that is a system page smaller than a bucket. GetSize()
- // should return a larger size than we asked for now.
- size_t num = 64;
- while (num * kSystemPageSize >= 1024 * 1024) {
- num /= 2;
- }
- requested_size = num * kSystemPageSize - kSystemPageSize - kExtraAllocSize;
- predicted_size = generic_allocator.root()->ActualSize(requested_size);
- ptr = generic_allocator.root()->Alloc(requested_size, type_name);
- EXPECT_TRUE(ptr);
- actual_size = PartitionAllocGetSize(ptr);
- EXPECT_EQ(predicted_size, actual_size);
- EXPECT_EQ(requested_size + kSystemPageSize, actual_size);
- // Check that we can write at the end of the reported size too.
- char* charPtr = reinterpret_cast<char*>(ptr);
- *(charPtr + (actual_size - 1)) = 'A';
- generic_allocator.root()->Free(ptr);
-
- // Allocate something very large, and uneven.
- if (IsLargeMemoryDevice()) {
- requested_size = 512 * 1024 * 1024 - 1;
- predicted_size = generic_allocator.root()->ActualSize(requested_size);
- ptr = generic_allocator.root()->Alloc(requested_size, type_name);
- EXPECT_TRUE(ptr);
- actual_size = PartitionAllocGetSize(ptr);
- EXPECT_EQ(predicted_size, actual_size);
- EXPECT_LT(requested_size, actual_size);
- generic_allocator.root()->Free(ptr);
- }
-
- // Too large allocation.
- requested_size = kGenericMaxDirectMapped + 1;
- predicted_size = generic_allocator.root()->ActualSize(requested_size);
- EXPECT_EQ(requested_size, predicted_size);
-}
-
-// Test the realloc() contract.
-TEST_F(PartitionAllocTest, Realloc) {
- // realloc(0, size) should be equivalent to malloc().
- void* ptr =
- generic_allocator.root()->Realloc(nullptr, kTestAllocSize, type_name);
- memset(ptr, 'A', kTestAllocSize);
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- // realloc(ptr, 0) should be equivalent to free().
- void* ptr2 = generic_allocator.root()->Realloc(ptr, 0, type_name);
- EXPECT_EQ(nullptr, ptr2);
- EXPECT_EQ(PartitionCookieFreePointerAdjust(ptr), page->freelist_head);
-
- // Test that growing an allocation with realloc() copies everything from the
- // old allocation.
- size_t size = kSystemPageSize - kExtraAllocSize;
- EXPECT_EQ(size, generic_allocator.root()->ActualSize(size));
- ptr = generic_allocator.root()->Alloc(size, type_name);
- memset(ptr, 'A', size);
- ptr2 = generic_allocator.root()->Realloc(ptr, size + 1, type_name);
- EXPECT_NE(ptr, ptr2);
- char* charPtr2 = static_cast<char*>(ptr2);
- EXPECT_EQ('A', charPtr2[0]);
- EXPECT_EQ('A', charPtr2[size - 1]);
-#if DCHECK_IS_ON()
- EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr2[size]));
-#endif
-
- // Test that shrinking an allocation with realloc() also copies everything
- // from the old allocation.
- ptr = generic_allocator.root()->Realloc(ptr2, size - 1, type_name);
- EXPECT_NE(ptr2, ptr);
- char* charPtr = static_cast<char*>(ptr);
- EXPECT_EQ('A', charPtr[0]);
- EXPECT_EQ('A', charPtr[size - 2]);
-#if DCHECK_IS_ON()
- EXPECT_EQ(kUninitializedByte, static_cast<unsigned char>(charPtr[size - 1]));
-#endif
-
- generic_allocator.root()->Free(ptr);
-
- // Test that shrinking a direct mapped allocation happens in-place.
- size = kGenericMaxBucketed + 16 * kSystemPageSize;
- ptr = generic_allocator.root()->Alloc(size, type_name);
- size_t actual_size = PartitionAllocGetSize(ptr);
- ptr2 = generic_allocator.root()->Realloc(
- ptr, kGenericMaxBucketed + 8 * kSystemPageSize, type_name);
- EXPECT_EQ(ptr, ptr2);
- EXPECT_EQ(actual_size - 8 * kSystemPageSize, PartitionAllocGetSize(ptr2));
-
- // Test that a previously in-place shrunk direct mapped allocation can be
- // expanded up again within its original size.
- ptr = generic_allocator.root()->Realloc(ptr2, size - kSystemPageSize,
- type_name);
- EXPECT_EQ(ptr2, ptr);
- EXPECT_EQ(actual_size - kSystemPageSize, PartitionAllocGetSize(ptr));
-
- // Test that a direct mapped allocation is performed not in-place when the
- // new size is small enough.
- ptr2 = generic_allocator.root()->Realloc(ptr, kSystemPageSize, type_name);
- EXPECT_NE(ptr, ptr2);
-
- generic_allocator.root()->Free(ptr2);
-}
-
-// Tests the handing out of freelists for partial pages.
-TEST_F(PartitionAllocTest, PartialPageFreelists) {
- size_t big_size = allocator.root()->max_allocation - kExtraAllocSize;
- EXPECT_EQ(kSystemPageSize - kAllocationGranularity,
- big_size + kExtraAllocSize);
- size_t bucket_index = (big_size + kExtraAllocSize) >> kBucketShift;
- PartitionBucket* bucket = &allocator.root()->buckets()[bucket_index];
- EXPECT_EQ(nullptr, bucket->empty_pages_head);
-
- void* ptr = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(ptr);
-
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- size_t totalSlots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
- (big_size + kExtraAllocSize);
- EXPECT_EQ(4u, totalSlots);
- // The freelist should have one entry, because we were able to exactly fit
- // one object slot and one freelist pointer (the null that the head points
- // to) into a system page.
- EXPECT_TRUE(page->freelist_head);
- EXPECT_EQ(1, page->num_allocated_slots);
- EXPECT_EQ(2, page->num_unprovisioned_slots);
-
- void* ptr2 = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(ptr2);
- EXPECT_FALSE(page->freelist_head);
- EXPECT_EQ(2, page->num_allocated_slots);
- EXPECT_EQ(2, page->num_unprovisioned_slots);
-
- void* ptr3 = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(ptr3);
- EXPECT_TRUE(page->freelist_head);
- EXPECT_EQ(3, page->num_allocated_slots);
- EXPECT_EQ(0, page->num_unprovisioned_slots);
-
- void* ptr4 = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(ptr4);
- EXPECT_FALSE(page->freelist_head);
- EXPECT_EQ(4, page->num_allocated_slots);
- EXPECT_EQ(0, page->num_unprovisioned_slots);
-
- void* ptr5 = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(ptr5);
-
- PartitionPage* page2 =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr5));
- EXPECT_EQ(1, page2->num_allocated_slots);
-
- // Churn things a little whilst there's a partial page freelist.
- PartitionFree(ptr);
- ptr = allocator.root()->Alloc(big_size, type_name);
- void* ptr6 = allocator.root()->Alloc(big_size, type_name);
-
- PartitionFree(ptr);
- PartitionFree(ptr2);
- PartitionFree(ptr3);
- PartitionFree(ptr4);
- PartitionFree(ptr5);
- PartitionFree(ptr6);
- EXPECT_NE(-1, page->empty_cache_index);
- EXPECT_NE(-1, page2->empty_cache_index);
- EXPECT_TRUE(page2->freelist_head);
- EXPECT_EQ(0, page2->num_allocated_slots);
-
- // And test a couple of sizes that do not cross kSystemPageSize with a single
- // allocation.
- size_t mediumSize = (kSystemPageSize / 2) - kExtraAllocSize;
- bucket_index = (mediumSize + kExtraAllocSize) >> kBucketShift;
- bucket = &allocator.root()->buckets()[bucket_index];
- EXPECT_EQ(nullptr, bucket->empty_pages_head);
-
- ptr = allocator.root()->Alloc(mediumSize, type_name);
- EXPECT_TRUE(ptr);
- page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(1, page->num_allocated_slots);
- totalSlots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
- (mediumSize + kExtraAllocSize);
- size_t firstPageSlots = kSystemPageSize / (mediumSize + kExtraAllocSize);
- EXPECT_EQ(2u, firstPageSlots);
- EXPECT_EQ(totalSlots - firstPageSlots, page->num_unprovisioned_slots);
-
- PartitionFree(ptr);
-
- size_t smallSize = (kSystemPageSize / 4) - kExtraAllocSize;
- bucket_index = (smallSize + kExtraAllocSize) >> kBucketShift;
- bucket = &allocator.root()->buckets()[bucket_index];
- EXPECT_EQ(nullptr, bucket->empty_pages_head);
-
- ptr = allocator.root()->Alloc(smallSize, type_name);
- EXPECT_TRUE(ptr);
- page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(1, page->num_allocated_slots);
- totalSlots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
- (smallSize + kExtraAllocSize);
- firstPageSlots = kSystemPageSize / (smallSize + kExtraAllocSize);
- EXPECT_EQ(totalSlots - firstPageSlots, page->num_unprovisioned_slots);
-
- PartitionFree(ptr);
- EXPECT_TRUE(page->freelist_head);
- EXPECT_EQ(0, page->num_allocated_slots);
-
- size_t verySmallSize = 32 - kExtraAllocSize;
- bucket_index = (verySmallSize + kExtraAllocSize) >> kBucketShift;
- bucket = &allocator.root()->buckets()[bucket_index];
- EXPECT_EQ(nullptr, bucket->empty_pages_head);
-
- ptr = allocator.root()->Alloc(verySmallSize, type_name);
- EXPECT_TRUE(ptr);
- page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(1, page->num_allocated_slots);
- totalSlots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
- (verySmallSize + kExtraAllocSize);
- firstPageSlots = kSystemPageSize / (verySmallSize + kExtraAllocSize);
- EXPECT_EQ(totalSlots - firstPageSlots, page->num_unprovisioned_slots);
-
- PartitionFree(ptr);
- EXPECT_TRUE(page->freelist_head);
- EXPECT_EQ(0, page->num_allocated_slots);
-
- // And try an allocation size (against the generic allocator) that is
- // larger than a system page.
- size_t pageAndAHalfSize =
- (kSystemPageSize + (kSystemPageSize / 2)) - kExtraAllocSize;
- ptr = generic_allocator.root()->Alloc(pageAndAHalfSize, type_name);
- EXPECT_TRUE(ptr);
- page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(1, page->num_allocated_slots);
- EXPECT_TRUE(page->freelist_head);
- totalSlots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
- (pageAndAHalfSize + kExtraAllocSize);
- EXPECT_EQ(totalSlots - 2, page->num_unprovisioned_slots);
- generic_allocator.root()->Free(ptr);
-
- // And then make sure than exactly the page size only faults one page.
- size_t pageSize = kSystemPageSize - kExtraAllocSize;
- ptr = generic_allocator.root()->Alloc(pageSize, type_name);
- EXPECT_TRUE(ptr);
- page = PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(1, page->num_allocated_slots);
- EXPECT_FALSE(page->freelist_head);
- totalSlots =
- (page->bucket->num_system_pages_per_slot_span * kSystemPageSize) /
- (pageSize + kExtraAllocSize);
- EXPECT_EQ(totalSlots - 1, page->num_unprovisioned_slots);
- generic_allocator.root()->Free(ptr);
-}
-
-// Test some of the fragmentation-resistant properties of the allocator.
-TEST_F(PartitionAllocTest, PageRefilling) {
- PartitionBucket* bucket = &allocator.root()->buckets()[kTestBucketIndex];
-
- // Grab two full pages and a non-full page.
- PartitionPage* page1 = GetFullPage(kTestAllocSize);
- PartitionPage* page2 = GetFullPage(kTestAllocSize);
- void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_TRUE(ptr);
- EXPECT_NE(page1, bucket->active_pages_head);
- EXPECT_NE(page2, bucket->active_pages_head);
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(1, page->num_allocated_slots);
-
- // Work out a pointer into page2 and free it; and then page1 and free it.
- char* ptr2 =
- reinterpret_cast<char*>(PartitionPage::ToPointer(page1)) + kPointerOffset;
- PartitionFree(ptr2);
- ptr2 =
- reinterpret_cast<char*>(PartitionPage::ToPointer(page2)) + kPointerOffset;
- PartitionFree(ptr2);
-
- // If we perform two allocations from the same bucket now, we expect to
- // refill both the nearly full pages.
- (void)allocator.root()->Alloc(kTestAllocSize, type_name);
- (void)allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_EQ(1, page->num_allocated_slots);
-
- FreeFullPage(page2);
- FreeFullPage(page1);
- PartitionFree(ptr);
-}
-
-// Basic tests to ensure that allocations work for partial page buckets.
-TEST_F(PartitionAllocTest, PartialPages) {
- // Find a size that is backed by a partial partition page.
- size_t size = sizeof(void*);
- PartitionBucket* bucket = nullptr;
- while (size < kTestMaxAllocation) {
- bucket = &allocator.root()->buckets()[size >> kBucketShift];
- if (bucket->num_system_pages_per_slot_span %
- kNumSystemPagesPerPartitionPage)
- break;
- size += sizeof(void*);
- }
- EXPECT_LT(size, kTestMaxAllocation);
-
- PartitionPage* page1 = GetFullPage(size);
- PartitionPage* page2 = GetFullPage(size);
- FreeFullPage(page2);
- FreeFullPage(page1);
-}
-
-// Test correct handling if our mapping collides with another.
-TEST_F(PartitionAllocTest, MappingCollision) {
- // The -2 is because the first and last partition pages in a super page are
- // guard pages.
- size_t numPartitionPagesNeeded = kNumPartitionPagesPerSuperPage - 2;
- auto firstSuperPagePages =
- std::make_unique<PartitionPage* []>(numPartitionPagesNeeded);
- auto secondSuperPagePages =
- std::make_unique<PartitionPage* []>(numPartitionPagesNeeded);
-
- size_t i;
- for (i = 0; i < numPartitionPagesNeeded; ++i)
- firstSuperPagePages[i] = GetFullPage(kTestAllocSize);
-
- char* pageBase =
- reinterpret_cast<char*>(PartitionPage::ToPointer(firstSuperPagePages[0]));
- EXPECT_EQ(kPartitionPageSize,
- reinterpret_cast<uintptr_t>(pageBase) & kSuperPageOffsetMask);
- pageBase -= kPartitionPageSize;
- // Map a single system page either side of the mapping for our allocations,
- // with the goal of tripping up alignment of the next mapping.
- void* map1 = AllocPages(pageBase - kPageAllocationGranularity,
- kPageAllocationGranularity,
- kPageAllocationGranularity, PageInaccessible);
- EXPECT_TRUE(map1);
- void* map2 = AllocPages(pageBase + kSuperPageSize, kPageAllocationGranularity,
- kPageAllocationGranularity, PageInaccessible);
- EXPECT_TRUE(map2);
-
- for (i = 0; i < numPartitionPagesNeeded; ++i)
- secondSuperPagePages[i] = GetFullPage(kTestAllocSize);
-
- FreePages(map1, kPageAllocationGranularity);
- FreePages(map2, kPageAllocationGranularity);
-
- pageBase = reinterpret_cast<char*>(
- PartitionPage::ToPointer(secondSuperPagePages[0]));
- EXPECT_EQ(kPartitionPageSize,
- reinterpret_cast<uintptr_t>(pageBase) & kSuperPageOffsetMask);
- pageBase -= kPartitionPageSize;
- // Map a single system page either side of the mapping for our allocations,
- // with the goal of tripping up alignment of the next mapping.
- map1 = AllocPages(pageBase - kPageAllocationGranularity,
- kPageAllocationGranularity, kPageAllocationGranularity,
- PageReadWrite);
- EXPECT_TRUE(map1);
- map2 = AllocPages(pageBase + kSuperPageSize, kPageAllocationGranularity,
- kPageAllocationGranularity, PageReadWrite);
- EXPECT_TRUE(map2);
- EXPECT_TRUE(
- SetSystemPagesAccess(map1, kPageAllocationGranularity, PageInaccessible));
- EXPECT_TRUE(
- SetSystemPagesAccess(map2, kPageAllocationGranularity, PageInaccessible));
-
- PartitionPage* pageInThirdSuperPage = GetFullPage(kTestAllocSize);
- FreePages(map1, kPageAllocationGranularity);
- FreePages(map2, kPageAllocationGranularity);
-
- EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(
- PartitionPage::ToPointer(pageInThirdSuperPage)) &
- kPartitionPageOffsetMask);
-
- // And make sure we really did get a page in a new superpage.
- EXPECT_NE(reinterpret_cast<uintptr_t>(
- PartitionPage::ToPointer(firstSuperPagePages[0])) &
- kSuperPageBaseMask,
- reinterpret_cast<uintptr_t>(
- PartitionPage::ToPointer(pageInThirdSuperPage)) &
- kSuperPageBaseMask);
- EXPECT_NE(reinterpret_cast<uintptr_t>(
- PartitionPage::ToPointer(secondSuperPagePages[0])) &
- kSuperPageBaseMask,
- reinterpret_cast<uintptr_t>(
- PartitionPage::ToPointer(pageInThirdSuperPage)) &
- kSuperPageBaseMask);
-
- FreeFullPage(pageInThirdSuperPage);
- for (i = 0; i < numPartitionPagesNeeded; ++i) {
- FreeFullPage(firstSuperPagePages[i]);
- FreeFullPage(secondSuperPagePages[i]);
- }
-}
-
-// Tests that pages in the free page cache do get freed as appropriate.
-TEST_F(PartitionAllocTest, FreeCache) {
- EXPECT_EQ(0U, allocator.root()->total_size_of_committed_pages);
-
- size_t big_size = allocator.root()->max_allocation - kExtraAllocSize;
- size_t bucket_index = (big_size + kExtraAllocSize) >> kBucketShift;
- PartitionBucket* bucket = &allocator.root()->buckets()[bucket_index];
-
- void* ptr = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(ptr);
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- EXPECT_EQ(nullptr, bucket->empty_pages_head);
- EXPECT_EQ(1, page->num_allocated_slots);
- EXPECT_EQ(kPartitionPageSize,
- allocator.root()->total_size_of_committed_pages);
- PartitionFree(ptr);
- EXPECT_EQ(0, page->num_allocated_slots);
- EXPECT_NE(-1, page->empty_cache_index);
- EXPECT_TRUE(page->freelist_head);
-
- CycleFreeCache(kTestAllocSize);
-
- // Flushing the cache should have really freed the unused page.
- EXPECT_FALSE(page->freelist_head);
- EXPECT_EQ(-1, page->empty_cache_index);
- EXPECT_EQ(0, page->num_allocated_slots);
- PartitionBucket* cycle_free_cache_bucket =
- &allocator.root()->buckets()[kTestBucketIndex];
- EXPECT_EQ(
- cycle_free_cache_bucket->num_system_pages_per_slot_span * kSystemPageSize,
- allocator.root()->total_size_of_committed_pages);
-
- // Check that an allocation works ok whilst in this state (a free'd page
- // as the active pages head).
- ptr = allocator.root()->Alloc(big_size, type_name);
- EXPECT_FALSE(bucket->empty_pages_head);
- PartitionFree(ptr);
-
- // Also check that a page that is bouncing immediately between empty and
- // used does not get freed.
- for (size_t i = 0; i < kMaxFreeableSpans * 2; ++i) {
- ptr = allocator.root()->Alloc(big_size, type_name);
- EXPECT_TRUE(page->freelist_head);
- PartitionFree(ptr);
- EXPECT_TRUE(page->freelist_head);
- }
- EXPECT_EQ(kPartitionPageSize,
- allocator.root()->total_size_of_committed_pages);
-}
-
-// Tests for a bug we had with losing references to free pages.
-TEST_F(PartitionAllocTest, LostFreePagesBug) {
- size_t size = kPartitionPageSize - kExtraAllocSize;
-
- void* ptr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr);
- void* ptr2 = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr2);
-
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr));
- PartitionPage* page2 =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr2));
- PartitionBucket* bucket = page->bucket;
-
- EXPECT_EQ(nullptr, bucket->empty_pages_head);
- EXPECT_EQ(-1, page->num_allocated_slots);
- EXPECT_EQ(1, page2->num_allocated_slots);
-
- generic_allocator.root()->Free(ptr);
- generic_allocator.root()->Free(ptr2);
-
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_TRUE(bucket->empty_pages_head->next_page);
- EXPECT_EQ(0, page->num_allocated_slots);
- EXPECT_EQ(0, page2->num_allocated_slots);
- EXPECT_TRUE(page->freelist_head);
- EXPECT_TRUE(page2->freelist_head);
-
- CycleGenericFreeCache(kTestAllocSize);
-
- EXPECT_FALSE(page->freelist_head);
- EXPECT_FALSE(page2->freelist_head);
-
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_TRUE(bucket->empty_pages_head->next_page);
- EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
-
- // At this moment, we have two decommitted pages, on the empty list.
- ptr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr);
- generic_allocator.root()->Free(ptr);
-
- EXPECT_EQ(PartitionPage::get_sentinel_page(), bucket->active_pages_head);
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_TRUE(bucket->decommitted_pages_head);
-
- CycleGenericFreeCache(kTestAllocSize);
-
- // We're now set up to trigger a historical bug by scanning over the active
- // pages list. The current code gets into a different state, but we'll keep
- // the test as being an interesting corner case.
- ptr = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_TRUE(ptr);
- generic_allocator.root()->Free(ptr);
-
- EXPECT_TRUE(bucket->active_pages_head);
- EXPECT_TRUE(bucket->empty_pages_head);
- EXPECT_TRUE(bucket->decommitted_pages_head);
-}
-
-// Unit tests that check if an allocation fails in "return null" mode,
-// repeating it doesn't crash, and still returns null. The tests need to
-// stress memory subsystem limits to do so, hence they try to allocate
-// 6 GB of memory, each with a different per-allocation block sizes.
-//
-// On 64-bit systems we need to restrict the address space to force allocation
-// failure, so these tests run only on POSIX systems that provide setrlimit(),
-// and use it to limit address space to 6GB.
-//
-// Disable these tests on Android because, due to the allocation-heavy behavior,
-// they tend to get OOM-killed rather than pass.
-// TODO(https://crbug.com/779645): Fuchsia currently sets OS_POSIX, but does
-// not provide a working setrlimit().
-#if !defined(ARCH_CPU_64_BITS) || \
- (defined(OS_POSIX) && \
- !(defined(OS_FUCHSIA) || defined(OS_MACOSX) || defined(OS_ANDROID)))
-
-// This is defined as a separate test class because RepeatedReturnNull
-// test exhausts the process memory, and breaks any test in the same
-// class that runs after it.
-class PartitionAllocReturnNullTest : public PartitionAllocTest {};
-
-// Test "return null" for larger, direct-mapped allocations first. As a
-// direct-mapped allocation's pages are unmapped and freed on release, this
-// test is performd first for these "return null" tests in order to leave
-// sufficient unreserved virtual memory around for the later one(s).
-TEST_F(PartitionAllocReturnNullTest, RepeatedReturnNullDirect) {
- // A direct-mapped allocation size.
- DoReturnNullTest(32 * 1024 * 1024, false);
-}
-
-// Test "return null" with a 512 kB block size.
-TEST_F(PartitionAllocReturnNullTest, RepeatedReturnNull) {
- // A single-slot but non-direct-mapped allocation size.
- DoReturnNullTest(512 * 1024, false);
-}
-
-// Repeating the above tests using Realloc instead of Alloc.
-class PartitionReallocReturnNullTest : public PartitionAllocTest {};
-
-TEST_F(PartitionReallocReturnNullTest, RepeatedReturnNullDirect) {
- DoReturnNullTest(32 * 1024 * 1024, true);
-}
-
-TEST_F(PartitionReallocReturnNullTest, RepeatedReturnNull) {
- DoReturnNullTest(512 * 1024, true);
-}
-
-#endif // !defined(ARCH_CPU_64_BITS) || (defined(OS_POSIX) &&
- // !(defined(OS_FUCHSIA) || defined(OS_MACOSX) || defined(OS_ANDROID)))
-
-// Death tests misbehave on Android, http://crbug.com/643760.
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-
-// Make sure that malloc(-1) dies.
-// In the past, we had an integer overflow that would alias malloc(-1) to
-// malloc(0), which is not good.
-TEST_F(PartitionAllocDeathTest, LargeAllocs) {
- // Largest alloc.
- EXPECT_DEATH(
- generic_allocator.root()->Alloc(static_cast<size_t>(-1), type_name), "");
- // And the smallest allocation we expect to die.
- EXPECT_DEATH(
- generic_allocator.root()->Alloc(kGenericMaxDirectMapped + 1, type_name),
- "");
-}
-
-// Check that our immediate double-free detection works.
-TEST_F(PartitionAllocDeathTest, ImmediateDoubleFree) {
- void* ptr = generic_allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_TRUE(ptr);
- generic_allocator.root()->Free(ptr);
-
- EXPECT_DEATH(generic_allocator.root()->Free(ptr), "");
-}
-
-// Check that our refcount-based double-free detection works.
-TEST_F(PartitionAllocDeathTest, RefcountDoubleFree) {
- void* ptr = generic_allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_TRUE(ptr);
- void* ptr2 = generic_allocator.root()->Alloc(kTestAllocSize, type_name);
- EXPECT_TRUE(ptr2);
- generic_allocator.root()->Free(ptr);
- generic_allocator.root()->Free(ptr2);
- // This is not an immediate double-free so our immediate detection won't
- // fire. However, it does take the "refcount" of the partition page to -1,
- // which is illegal and should be trapped.
- EXPECT_DEATH(generic_allocator.root()->Free(ptr), "");
-}
-
-// Check that guard pages are present where expected.
-TEST_F(PartitionAllocDeathTest, GuardPages) {
-// PartitionAlloc adds kPartitionPageSize to the requested size
-// (for metadata), and then rounds that size to kPageAllocationGranularity.
-// To be able to reliably write one past a direct allocation, choose a size
-// that's
-// a) larger than kGenericMaxBucketed (to make the allocation direct)
-// b) aligned at kPageAllocationGranularity boundaries after
-// kPartitionPageSize has been added to it.
-// (On 32-bit, PartitionAlloc adds another kSystemPageSize to the
-// allocation size before rounding, but there it marks the memory right
-// after size as inaccessible, so it's fine to write 1 past the size we
-// hand to PartitionAlloc and we don't need to worry about allocation
-// granularities.)
-#define ALIGN(N, A) (((N) + (A)-1) / (A) * (A))
- const int kSize = ALIGN(kGenericMaxBucketed + 1 + kPartitionPageSize,
- kPageAllocationGranularity) -
- kPartitionPageSize;
-#undef ALIGN
- static_assert(kSize > kGenericMaxBucketed,
- "allocation not large enough for direct allocation");
- size_t size = kSize - kExtraAllocSize;
- void* ptr = generic_allocator.root()->Alloc(size, type_name);
-
- EXPECT_TRUE(ptr);
- char* charPtr = reinterpret_cast<char*>(ptr) - kPointerOffset;
-
- EXPECT_DEATH(*(charPtr - 1) = 'A', "");
- EXPECT_DEATH(*(charPtr + size + kExtraAllocSize) = 'A', "");
-
- generic_allocator.root()->Free(ptr);
-}
-
-// Check that a bad free() is caught where the free() refers to an unused
-// partition page of a large allocation.
-TEST_F(PartitionAllocDeathTest, FreeWrongPartitionPage) {
- // This large size will result in a direct mapped allocation with guard
- // pages at either end.
- void* ptr =
- generic_allocator.root()->Alloc(kPartitionPageSize * 2, type_name);
- EXPECT_TRUE(ptr);
- char* badPtr = reinterpret_cast<char*>(ptr) + kPartitionPageSize;
-
- EXPECT_DEATH(generic_allocator.root()->Free(badPtr), "");
-
- generic_allocator.root()->Free(ptr);
-}
-
-#endif // !defined(OS_ANDROID) && !defined(OS_IOS)
-
-// Tests that |PartitionDumpStatsGeneric| and |PartitionDumpStats| run without
-// crashing and return non-zero values when memory is allocated.
-TEST_F(PartitionAllocTest, DumpMemoryStats) {
- {
- void* ptr = allocator.root()->Alloc(kTestAllocSize, type_name);
- MockPartitionStatsDumper mockStatsDumper;
- allocator.root()->DumpStats("mock_allocator", false /* detailed dump */,
- &mockStatsDumper);
- EXPECT_TRUE(mockStatsDumper.IsMemoryAllocationRecorded());
- PartitionFree(ptr);
- }
-
- // This series of tests checks the active -> empty -> decommitted states.
- {
- {
- void* ptr =
- generic_allocator.root()->Alloc(2048 - kExtraAllocSize, type_name);
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats = dumper.GetBucketStats(2048);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(2048u, stats->bucket_slot_size);
- EXPECT_EQ(2048u, stats->active_bytes);
- EXPECT_EQ(kSystemPageSize, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(0u, stats->num_full_pages);
- EXPECT_EQ(1u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
- generic_allocator.root()->Free(ptr);
- }
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_FALSE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats = dumper.GetBucketStats(2048);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(2048u, stats->bucket_slot_size);
- EXPECT_EQ(0u, stats->active_bytes);
- EXPECT_EQ(kSystemPageSize, stats->resident_bytes);
- EXPECT_EQ(kSystemPageSize, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(0u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(1u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
- }
-
- // TODO(crbug.com/722911): Commenting this out causes this test to fail when
- // run singly (--gtest_filter=PartitionAllocTest.DumpMemoryStats), but not
- // when run with the others (--gtest_filter=PartitionAllocTest.*).
- CycleGenericFreeCache(kTestAllocSize);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_FALSE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats = dumper.GetBucketStats(2048);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(2048u, stats->bucket_slot_size);
- EXPECT_EQ(0u, stats->active_bytes);
- EXPECT_EQ(0u, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(0u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(1u, stats->num_decommitted_pages);
- }
- }
-
- // This test checks for correct empty page list accounting.
- {
- size_t size = kPartitionPageSize - kExtraAllocSize;
- void* ptr1 = generic_allocator.root()->Alloc(size, type_name);
- void* ptr2 = generic_allocator.root()->Alloc(size, type_name);
- generic_allocator.root()->Free(ptr1);
- generic_allocator.root()->Free(ptr2);
-
- CycleGenericFreeCache(kTestAllocSize);
-
- ptr1 = generic_allocator.root()->Alloc(size, type_name);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(kPartitionPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(kPartitionPageSize, stats->bucket_slot_size);
- EXPECT_EQ(kPartitionPageSize, stats->active_bytes);
- EXPECT_EQ(kPartitionPageSize, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(1u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(1u, stats->num_decommitted_pages);
- }
- generic_allocator.root()->Free(ptr1);
- }
-
- // This test checks for correct direct mapped accounting.
- {
- size_t size_smaller = kGenericMaxBucketed + 1;
- size_t size_bigger = (kGenericMaxBucketed * 2) + 1;
- size_t real_size_smaller =
- (size_smaller + kSystemPageOffsetMask) & kSystemPageBaseMask;
- size_t real_size_bigger =
- (size_bigger + kSystemPageOffsetMask) & kSystemPageBaseMask;
- void* ptr = generic_allocator.root()->Alloc(size_smaller, type_name);
- void* ptr2 = generic_allocator.root()->Alloc(size_bigger, type_name);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(real_size_smaller);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_TRUE(stats->is_direct_map);
- EXPECT_EQ(real_size_smaller, stats->bucket_slot_size);
- EXPECT_EQ(real_size_smaller, stats->active_bytes);
- EXPECT_EQ(real_size_smaller, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(1u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
-
- stats = dumper.GetBucketStats(real_size_bigger);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_TRUE(stats->is_direct_map);
- EXPECT_EQ(real_size_bigger, stats->bucket_slot_size);
- EXPECT_EQ(real_size_bigger, stats->active_bytes);
- EXPECT_EQ(real_size_bigger, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(1u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
- }
-
- generic_allocator.root()->Free(ptr2);
- generic_allocator.root()->Free(ptr);
-
- // Whilst we're here, allocate again and free with different ordering to
- // give a workout to our linked list code.
- ptr = generic_allocator.root()->Alloc(size_smaller, type_name);
- ptr2 = generic_allocator.root()->Alloc(size_bigger, type_name);
- generic_allocator.root()->Free(ptr);
- generic_allocator.root()->Free(ptr2);
- }
-
- // This test checks large-but-not-quite-direct allocations.
- {
- constexpr size_t requested_size = 16 * kSystemPageSize;
- void* ptr = generic_allocator.root()->Alloc(requested_size + 1, type_name);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- size_t slot_size =
- requested_size + (requested_size / kGenericNumBucketsPerOrder);
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(slot_size);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_FALSE(stats->is_direct_map);
- EXPECT_EQ(slot_size, stats->bucket_slot_size);
- EXPECT_EQ(requested_size + 1 + kExtraAllocSize, stats->active_bytes);
- EXPECT_EQ(slot_size, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
- EXPECT_EQ(1u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
- }
-
- generic_allocator.root()->Free(ptr);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_FALSE(dumper.IsMemoryAllocationRecorded());
-
- size_t slot_size =
- requested_size + (requested_size / kGenericNumBucketsPerOrder);
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(slot_size);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_FALSE(stats->is_direct_map);
- EXPECT_EQ(slot_size, stats->bucket_slot_size);
- EXPECT_EQ(0u, stats->active_bytes);
- EXPECT_EQ(slot_size, stats->resident_bytes);
- EXPECT_EQ(slot_size, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(1u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
- }
-
- void* ptr2 = generic_allocator.root()->Alloc(
- requested_size + kSystemPageSize + 1, type_name);
- EXPECT_EQ(ptr, ptr2);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- size_t slot_size =
- requested_size + (requested_size / kGenericNumBucketsPerOrder);
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(slot_size);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_FALSE(stats->is_direct_map);
- EXPECT_EQ(slot_size, stats->bucket_slot_size);
- EXPECT_EQ(requested_size + kSystemPageSize + 1 + kExtraAllocSize,
- stats->active_bytes);
- EXPECT_EQ(slot_size, stats->resident_bytes);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->discardable_bytes);
- EXPECT_EQ(1u, stats->num_full_pages);
- EXPECT_EQ(0u, stats->num_active_pages);
- EXPECT_EQ(0u, stats->num_empty_pages);
- EXPECT_EQ(0u, stats->num_decommitted_pages);
- }
-
- generic_allocator.root()->Free(ptr2);
- }
-}
-
-// Tests the API to purge freeable memory.
-TEST_F(PartitionAllocTest, Purge) {
- char* ptr = reinterpret_cast<char*>(
- generic_allocator.root()->Alloc(2048 - kExtraAllocSize, type_name));
- generic_allocator.root()->Free(ptr);
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_FALSE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats = dumper.GetBucketStats(2048);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(kSystemPageSize, stats->decommittable_bytes);
- EXPECT_EQ(kSystemPageSize, stats->resident_bytes);
- }
- generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_FALSE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats = dumper.GetBucketStats(2048);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(0u, stats->resident_bytes);
- }
- // Calling purge again here is a good way of testing we didn't mess up the
- // state of the free cache ring.
- generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
-
- char* bigPtr = reinterpret_cast<char*>(
- generic_allocator.root()->Alloc(256 * 1024, type_name));
- generic_allocator.root()->Free(bigPtr);
- generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
-
- CHECK_PAGE_IN_CORE(ptr - kPointerOffset, false);
- CHECK_PAGE_IN_CORE(bigPtr - kPointerOffset, false);
-}
-
-// Tests that we prefer to allocate into a non-empty partition page over an
-// empty one. This is an important aspect of minimizing memory usage for some
-// allocation sizes, particularly larger ones.
-TEST_F(PartitionAllocTest, PreferActiveOverEmpty) {
- size_t size = (kSystemPageSize * 2) - kExtraAllocSize;
- // Allocate 3 full slot spans worth of 8192-byte allocations.
- // Each slot span for this size is 16384 bytes, or 1 partition page and 2
- // slots.
- void* ptr1 = generic_allocator.root()->Alloc(size, type_name);
- void* ptr2 = generic_allocator.root()->Alloc(size, type_name);
- void* ptr3 = generic_allocator.root()->Alloc(size, type_name);
- void* ptr4 = generic_allocator.root()->Alloc(size, type_name);
- void* ptr5 = generic_allocator.root()->Alloc(size, type_name);
- void* ptr6 = generic_allocator.root()->Alloc(size, type_name);
-
- PartitionPage* page1 =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr1));
- PartitionPage* page2 =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr3));
- PartitionPage* page3 =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr6));
- EXPECT_NE(page1, page2);
- EXPECT_NE(page2, page3);
- PartitionBucket* bucket = page1->bucket;
- EXPECT_EQ(page3, bucket->active_pages_head);
-
- // Free up the 2nd slot in each slot span.
- // This leaves the active list containing 3 pages, each with 1 used and 1
- // free slot. The active page will be the one containing ptr1.
- generic_allocator.root()->Free(ptr6);
- generic_allocator.root()->Free(ptr4);
- generic_allocator.root()->Free(ptr2);
- EXPECT_EQ(page1, bucket->active_pages_head);
-
- // Empty the middle page in the active list.
- generic_allocator.root()->Free(ptr3);
- EXPECT_EQ(page1, bucket->active_pages_head);
-
- // Empty the the first page in the active list -- also the current page.
- generic_allocator.root()->Free(ptr1);
-
- // A good choice here is to re-fill the third page since the first two are
- // empty. We used to fail that.
- void* ptr7 = generic_allocator.root()->Alloc(size, type_name);
- EXPECT_EQ(ptr6, ptr7);
- EXPECT_EQ(page3, bucket->active_pages_head);
-
- generic_allocator.root()->Free(ptr5);
- generic_allocator.root()->Free(ptr7);
-}
-
-// Tests the API to purge discardable memory.
-TEST_F(PartitionAllocTest, PurgeDiscardable) {
- // Free the second of two 4096 byte allocations and then purge.
- {
- void* ptr1 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- char* ptr2 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name));
- generic_allocator.root()->Free(ptr2);
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr1));
- EXPECT_EQ(2u, page->num_unprovisioned_slots);
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(kSystemPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
- EXPECT_EQ(kSystemPageSize, stats->active_bytes);
- EXPECT_EQ(2 * kSystemPageSize, stats->resident_bytes);
- }
- CHECK_PAGE_IN_CORE(ptr2 - kPointerOffset, true);
- generic_allocator.root()->PurgeMemory(
- PartitionPurgeDiscardUnusedSystemPages);
- CHECK_PAGE_IN_CORE(ptr2 - kPointerOffset, false);
- EXPECT_EQ(3u, page->num_unprovisioned_slots);
-
- generic_allocator.root()->Free(ptr1);
- }
- // Free the first of two 4096 byte allocations and then purge.
- {
- char* ptr1 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name));
- void* ptr2 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- generic_allocator.root()->Free(ptr1);
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(kSystemPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
-#if defined(OS_WIN)
- EXPECT_EQ(0u, stats->discardable_bytes);
-#else
- EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
-#endif
- EXPECT_EQ(kSystemPageSize, stats->active_bytes);
- EXPECT_EQ(2 * kSystemPageSize, stats->resident_bytes);
- }
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- generic_allocator.root()->PurgeMemory(
- PartitionPurgeDiscardUnusedSystemPages);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, false);
-
- generic_allocator.root()->Free(ptr2);
- }
- {
- constexpr size_t requested_size = 2.25 * kSystemPageSize;
- char* ptr1 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- requested_size - kExtraAllocSize, type_name));
- void* ptr2 = generic_allocator.root()->Alloc(
- requested_size - kExtraAllocSize, type_name);
- void* ptr3 = generic_allocator.root()->Alloc(
- requested_size - kExtraAllocSize, type_name);
- void* ptr4 = generic_allocator.root()->Alloc(
- requested_size - kExtraAllocSize, type_name);
- memset(ptr1, 'A', requested_size - kExtraAllocSize);
- memset(ptr2, 'A', requested_size - kExtraAllocSize);
- generic_allocator.root()->Free(ptr2);
- generic_allocator.root()->Free(ptr1);
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(requested_size);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(2 * kSystemPageSize, stats->discardable_bytes);
- EXPECT_EQ(requested_size * 2, stats->active_bytes);
- EXPECT_EQ(9 * kSystemPageSize, stats->resident_bytes);
- }
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + kSystemPageSize, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 2), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 3), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 4), true);
- generic_allocator.root()->PurgeMemory(
- PartitionPurgeDiscardUnusedSystemPages);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + kSystemPageSize, false);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 2), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 3), false);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 4), true);
-
- generic_allocator.root()->Free(ptr3);
- generic_allocator.root()->Free(ptr4);
- }
-
-// When kSystemPageSize = 16384 (as on _MIPS_ARCH_LOONGSON), 64 *
-// kSystemPageSize (see the #else branch below) caused this test to OOM.
-// Therefore, for systems with 16 KiB pages, use 32 * kSystemPageSize.
-//
-// TODO(palmer): Refactor this to branch on page size instead of architecture,
-// for clarity of purpose and for applicability to more architectures.
-#if defined(_MIPS_ARCH_LOONGSON)
- {
- char* ptr1 = reinterpret_cast<char*>(PartitionAllocGeneric(
- generic_allocator.root(), (32 * kSystemPageSize) - kExtraAllocSize,
- type_name));
- memset(ptr1, 'A', (32 * kSystemPageSize) - kExtraAllocSize);
- PartitionFreeGeneric(generic_allocator.root(), ptr1);
- ptr1 = reinterpret_cast<char*>(PartitionAllocGeneric(
- generic_allocator.root(), (31 * kSystemPageSize) - kExtraAllocSize,
- type_name));
- {
- MockPartitionStatsDumper dumper;
- PartitionDumpStatsGeneric(generic_allocator.root(),
- "mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(32 * kSystemPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
- EXPECT_EQ(31 * kSystemPageSize, stats->active_bytes);
- EXPECT_EQ(32 * kSystemPageSize, stats->resident_bytes);
- }
- CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 30), true);
- CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 31), true);
- PartitionPurgeMemoryGeneric(generic_allocator.root(),
- PartitionPurgeDiscardUnusedSystemPages);
- CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 30), true);
- CheckPageInCore(ptr1 - kPointerOffset + (kSystemPageSize * 31), false);
-
- PartitionFreeGeneric(generic_allocator.root(), ptr1);
- }
-#else
- {
- char* ptr1 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- (64 * kSystemPageSize) - kExtraAllocSize, type_name));
- memset(ptr1, 'A', (64 * kSystemPageSize) - kExtraAllocSize);
- generic_allocator.root()->Free(ptr1);
- ptr1 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- (61 * kSystemPageSize) - kExtraAllocSize, type_name));
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(64 * kSystemPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(3 * kSystemPageSize, stats->discardable_bytes);
- EXPECT_EQ(61 * kSystemPageSize, stats->active_bytes);
- EXPECT_EQ(64 * kSystemPageSize, stats->resident_bytes);
- }
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 60), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 61), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 62), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 63), true);
- generic_allocator.root()->PurgeMemory(
- PartitionPurgeDiscardUnusedSystemPages);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 60), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 61), false);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 62), false);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 63), false);
-
- generic_allocator.root()->Free(ptr1);
- }
-#endif
- // This sub-test tests truncation of the provisioned slots in a trickier
- // case where the freelist is rewritten.
- generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
- {
- char* ptr1 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name));
- void* ptr2 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- void* ptr3 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- void* ptr4 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- ptr1[0] = 'A';
- ptr1[kSystemPageSize] = 'A';
- ptr1[kSystemPageSize * 2] = 'A';
- ptr1[kSystemPageSize * 3] = 'A';
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr1));
- generic_allocator.root()->Free(ptr2);
- generic_allocator.root()->Free(ptr4);
- generic_allocator.root()->Free(ptr1);
- EXPECT_EQ(0u, page->num_unprovisioned_slots);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(kSystemPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
-#if defined(OS_WIN)
- EXPECT_EQ(kSystemPageSize, stats->discardable_bytes);
-#else
- EXPECT_EQ(2 * kSystemPageSize, stats->discardable_bytes);
-#endif
- EXPECT_EQ(kSystemPageSize, stats->active_bytes);
- EXPECT_EQ(4 * kSystemPageSize, stats->resident_bytes);
- }
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + kSystemPageSize, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 2), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 3), true);
- generic_allocator.root()->PurgeMemory(
- PartitionPurgeDiscardUnusedSystemPages);
- EXPECT_EQ(1u, page->num_unprovisioned_slots);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + kSystemPageSize, false);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 2), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 3), false);
-
- // Let's check we didn't brick the freelist.
- void* ptr1b = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- EXPECT_EQ(ptr1, ptr1b);
- void* ptr2b = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- EXPECT_EQ(ptr2, ptr2b);
- EXPECT_FALSE(page->freelist_head);
-
- generic_allocator.root()->Free(ptr1);
- generic_allocator.root()->Free(ptr2);
- generic_allocator.root()->Free(ptr3);
- }
- // This sub-test is similar, but tests a double-truncation.
- generic_allocator.root()->PurgeMemory(PartitionPurgeDecommitEmptyPages);
- {
- char* ptr1 = reinterpret_cast<char*>(generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name));
- void* ptr2 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- void* ptr3 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- void* ptr4 = generic_allocator.root()->Alloc(
- kSystemPageSize - kExtraAllocSize, type_name);
- ptr1[0] = 'A';
- ptr1[kSystemPageSize] = 'A';
- ptr1[kSystemPageSize * 2] = 'A';
- ptr1[kSystemPageSize * 3] = 'A';
- PartitionPage* page =
- PartitionPage::FromPointer(PartitionCookieFreePointerAdjust(ptr1));
- generic_allocator.root()->Free(ptr4);
- generic_allocator.root()->Free(ptr3);
- EXPECT_EQ(0u, page->num_unprovisioned_slots);
-
- {
- MockPartitionStatsDumper dumper;
- generic_allocator.root()->DumpStats("mock_generic_allocator",
- false /* detailed dump */, &dumper);
- EXPECT_TRUE(dumper.IsMemoryAllocationRecorded());
-
- const PartitionBucketMemoryStats* stats =
- dumper.GetBucketStats(kSystemPageSize);
- EXPECT_TRUE(stats);
- EXPECT_TRUE(stats->is_valid);
- EXPECT_EQ(0u, stats->decommittable_bytes);
- EXPECT_EQ(2 * kSystemPageSize, stats->discardable_bytes);
- EXPECT_EQ(2 * kSystemPageSize, stats->active_bytes);
- EXPECT_EQ(4 * kSystemPageSize, stats->resident_bytes);
- }
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + kSystemPageSize, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 2), true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 3), true);
- generic_allocator.root()->PurgeMemory(
- PartitionPurgeDiscardUnusedSystemPages);
- EXPECT_EQ(2u, page->num_unprovisioned_slots);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + kSystemPageSize, true);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 2), false);
- CHECK_PAGE_IN_CORE(ptr1 - kPointerOffset + (kSystemPageSize * 3), false);
-
- EXPECT_FALSE(page->freelist_head);
-
- generic_allocator.root()->Free(ptr1);
- generic_allocator.root()->Free(ptr2);
- }
-}
-
-TEST_F(PartitionAllocTest, ReallocMovesCookies) {
- // Resize so as to be sure to hit a "resize in place" case, and ensure that
- // use of the entire result is compatible with the debug mode's cookies, even
- // when the bucket size is large enough to span more than one partition page
- // and we can track the "raw" size. See https://crbug.com/709271
- static constexpr size_t kSize =
- base::kMaxSystemPagesPerSlotSpan * base::kSystemPageSize;
- void* ptr = generic_allocator.root()->Alloc(kSize + 1, type_name);
- EXPECT_TRUE(ptr);
-
- memset(ptr, 0xbd, kSize + 1);
- ptr = generic_allocator.root()->Realloc(ptr, kSize + 2, type_name);
- EXPECT_TRUE(ptr);
-
- memset(ptr, 0xbd, kSize + 2);
- generic_allocator.root()->Free(ptr);
-}
-
-TEST_F(PartitionAllocTest, SmallReallocDoesNotMoveTrailingCookie) {
- // For crbug.com/781473
- static constexpr size_t kSize = 264;
- void* ptr = generic_allocator.root()->Alloc(kSize, type_name);
- EXPECT_TRUE(ptr);
-
- ptr = generic_allocator.root()->Realloc(ptr, kSize + 16, type_name);
- EXPECT_TRUE(ptr);
-
- generic_allocator.root()->Free(ptr);
-}
-
-} // namespace internal
-} // namespace base
-
-#endif // !defined(MEMORY_TOOL_REPLACES_ALLOCATOR)
diff --git a/base/allocator/partition_allocator/spin_lock_unittest.cc b/base/allocator/partition_allocator/spin_lock_unittest.cc
deleted file mode 100644
index 6a1fd6b..0000000
--- a/base/allocator/partition_allocator/spin_lock_unittest.cc
+++ /dev/null
@@ -1,61 +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/allocator/partition_allocator/spin_lock.h"
-
-#include <memory>
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-static const size_t kBufferSize = 16;
-
-static subtle::SpinLock g_lock;
-
-static void FillBuffer(volatile char* buffer, char fill_pattern) {
- for (size_t i = 0; i < kBufferSize; ++i)
- buffer[i] = fill_pattern;
-}
-
-static void ChangeAndCheckBuffer(volatile char* buffer) {
- FillBuffer(buffer, '\0');
- int total = 0;
- for (size_t i = 0; i < kBufferSize; ++i)
- total += buffer[i];
-
- EXPECT_EQ(0, total);
-
- // This will mess with the other thread's calculation if we accidentally get
- // concurrency.
- FillBuffer(buffer, '!');
-}
-
-static void ThreadMain(volatile char* buffer) {
- for (int i = 0; i < 500000; ++i) {
- subtle::SpinLock::Guard guard(g_lock);
- ChangeAndCheckBuffer(buffer);
- }
-}
-
-TEST(SpinLockTest, Torture) {
- char shared_buffer[kBufferSize];
-
- Thread thread1("thread1");
- Thread thread2("thread2");
-
- thread1.StartAndWaitForTesting();
- thread2.StartAndWaitForTesting();
-
- thread1.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&ThreadMain, Unretained(static_cast<char*>(shared_buffer))));
- thread2.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&ThreadMain, Unretained(static_cast<char*>(shared_buffer))));
-}
-
-} // namespace base
diff --git a/base/allocator/tcmalloc_unittest.cc b/base/allocator/tcmalloc_unittest.cc
deleted file mode 100644
index 4b5b664..0000000
--- a/base/allocator/tcmalloc_unittest.cc
+++ /dev/null
@@ -1,235 +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 <stdio.h>
-
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/process/process_metrics.h"
-#include "base/sys_info.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(USE_TCMALLOC)
-namespace {
-
-using std::min;
-
-#ifdef NDEBUG
-// We wrap malloc and free in noinline functions to ensure that we test the real
-// implementation of the allocator. Otherwise, the compiler may specifically
-// recognize the calls to malloc and free in our tests and optimize them away.
-NOINLINE void* TCMallocDoMallocForTest(size_t size) {
- return malloc(size);
-}
-
-NOINLINE void TCMallocDoFreeForTest(void* ptr) {
- free(ptr);
-}
-#endif
-
-// Fill a buffer of the specified size with a predetermined pattern
-static void Fill(unsigned char* buffer, int n) {
- for (int i = 0; i < n; i++) {
- buffer[i] = (i & 0xff);
- }
-}
-
-// Check that the specified buffer has the predetermined pattern
-// generated by Fill()
-static bool Valid(unsigned char* buffer, int n) {
- for (int i = 0; i < n; i++) {
- if (buffer[i] != (i & 0xff)) {
- return false;
- }
- }
- return true;
-}
-
-// Return the next interesting size/delta to check. Returns -1 if no more.
-static int NextSize(int size) {
- if (size < 100)
- return size + 1;
-
- if (size < 100000) {
- // Find next power of two
- int power = 1;
- while (power < size)
- power <<= 1;
-
- // Yield (power-1, power, power+1)
- if (size < power - 1)
- return power - 1;
-
- if (size == power - 1)
- return power;
-
- CHECK_EQ(size, power);
- return power + 1;
- } else {
- return -1;
- }
-}
-
-static void TestCalloc(size_t n, size_t s, bool ok) {
- char* p = reinterpret_cast<char*>(calloc(n, s));
- if (!ok) {
- EXPECT_EQ(nullptr, p) << "calloc(n, s) should not succeed";
- } else {
- EXPECT_NE(reinterpret_cast<void*>(NULL), p)
- << "calloc(n, s) should succeed";
- for (size_t i = 0; i < n * s; i++) {
- EXPECT_EQ('\0', p[i]);
- }
- free(p);
- }
-}
-
-bool IsLowMemoryDevice() {
- return base::SysInfo::AmountOfPhysicalMemory() <= 256LL * 1024 * 1024;
-}
-
-} // namespace
-
-TEST(TCMallocTest, Malloc) {
- // Try allocating data with a bunch of alignments and sizes
- for (int size = 1; size < 1048576; size *= 2) {
- unsigned char* ptr = reinterpret_cast<unsigned char*>(malloc(size));
- // Should be 2 byte aligned
- EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & 1);
- Fill(ptr, size);
- EXPECT_TRUE(Valid(ptr, size));
- free(ptr);
- }
-}
-
-TEST(TCMallocTest, Calloc) {
- TestCalloc(0, 0, true);
- TestCalloc(0, 1, true);
- TestCalloc(1, 1, true);
- TestCalloc(1 << 10, 0, true);
- TestCalloc(1 << 20, 0, true);
- TestCalloc(0, 1 << 10, true);
- TestCalloc(0, 1 << 20, true);
- TestCalloc(1 << 20, 2, true);
- TestCalloc(2, 1 << 20, true);
- TestCalloc(1000, 1000, true);
-}
-
-#ifdef NDEBUG
-// This makes sure that reallocing a small number of bytes in either
-// direction doesn't cause us to allocate new memory. Tcmalloc in debug mode
-// does not follow this.
-TEST(TCMallocTest, ReallocSmallDelta) {
- int start_sizes[] = {100, 1000, 10000, 100000};
- int deltas[] = {1, -2, 4, -8, 16, -32, 64, -128};
-
- for (unsigned s = 0; s < sizeof(start_sizes) / sizeof(*start_sizes); ++s) {
- void* p = malloc(start_sizes[s]);
- ASSERT_TRUE(p);
- // The larger the start-size, the larger the non-reallocing delta.
- for (unsigned d = 0; d < s * 2; ++d) {
- void* new_p = realloc(p, start_sizes[s] + deltas[d]);
- ASSERT_EQ(p, new_p); // realloc should not allocate new memory
- }
- // Test again, but this time reallocing smaller first.
- for (unsigned d = 0; d < s * 2; ++d) {
- void* new_p = realloc(p, start_sizes[s] - deltas[d]);
- ASSERT_EQ(p, new_p); // realloc should not allocate new memory
- }
- free(p);
- }
-}
-#endif
-
-TEST(TCMallocTest, Realloc) {
- for (int src_size = 0; src_size >= 0; src_size = NextSize(src_size)) {
- for (int dst_size = 0; dst_size >= 0; dst_size = NextSize(dst_size)) {
- unsigned char* src = reinterpret_cast<unsigned char*>(malloc(src_size));
- Fill(src, src_size);
- unsigned char* dst =
- reinterpret_cast<unsigned char*>(realloc(src, dst_size));
- EXPECT_TRUE(Valid(dst, min(src_size, dst_size)));
- Fill(dst, dst_size);
- EXPECT_TRUE(Valid(dst, dst_size));
- if (dst != nullptr)
- free(dst);
- }
- }
-
- // The logic below tries to allocate kNumEntries * 9000 ~= 130 MB of memory.
- // This would cause the test to crash on low memory devices with no VM
- // overcommit (e.g., chromecast).
- if (IsLowMemoryDevice())
- return;
-
- // Now make sure realloc works correctly even when we overflow the
- // packed cache, so some entries are evicted from the cache.
- // The cache has 2^12 entries, keyed by page number.
- const int kNumEntries = 1 << 14;
- int** p = reinterpret_cast<int**>(malloc(sizeof(*p) * kNumEntries));
- int sum = 0;
- for (int i = 0; i < kNumEntries; i++) {
- // no page size is likely to be bigger than 8192?
- p[i] = reinterpret_cast<int*>(malloc(8192));
- p[i][1000] = i; // use memory deep in the heart of p
- }
- for (int i = 0; i < kNumEntries; i++) {
- p[i] = reinterpret_cast<int*>(realloc(p[i], 9000));
- }
- for (int i = 0; i < kNumEntries; i++) {
- sum += p[i][1000];
- free(p[i]);
- }
- EXPECT_EQ(kNumEntries / 2 * (kNumEntries - 1), sum); // assume kNE is even
- free(p);
-}
-
-#ifdef NDEBUG
-TEST(TCMallocFreeTest, BadPointerInFirstPageOfTheLargeObject) {
- const size_t kPageSize = base::GetPageSize();
- char* p =
- reinterpret_cast<char*>(TCMallocDoMallocForTest(10 * kPageSize + 1));
- for (unsigned offset = 1; offset < kPageSize; offset <<= 1) {
- ASSERT_DEATH(TCMallocDoFreeForTest(p + offset),
- "Pointer is not pointing to the start of a span");
- }
- TCMallocDoFreeForTest(p);
-}
-
-// TODO(ssid): Fix flakiness and enable the test, crbug.com/571549.
-TEST(TCMallocFreeTest, DISABLED_BadPageAlignedPointerInsideLargeObject) {
- const size_t kPageSize = base::GetPageSize();
- const size_t kMaxSize = 10 * kPageSize;
- char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(kMaxSize + 1));
-
- for (unsigned offset = kPageSize; offset < kMaxSize; offset += kPageSize) {
- // Only the first and last page of a span are in heap map. So for others
- // tcmalloc will give a general error of invalid pointer.
- ASSERT_DEATH(TCMallocDoFreeForTest(p + offset), "");
- }
- ASSERT_DEATH(TCMallocDoFreeForTest(p + kMaxSize),
- "Pointer is not pointing to the start of a span");
- TCMallocDoFreeForTest(p);
-}
-
-TEST(TCMallocFreeTest, DoubleFreeLargeObject) {
- const size_t kMaxSize = 10 * base::GetPageSize();
- char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(kMaxSize + 1));
- ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p),
- "Object was not in-use");
-}
-
-TEST(TCMallocFreeTest, DoubleFreeSmallObject) {
- const size_t kPageSize = base::GetPageSize();
- for (size_t size = 1; size <= kPageSize; size <<= 1) {
- char* p = reinterpret_cast<char*>(TCMallocDoMallocForTest(size));
- ASSERT_DEATH(TCMallocDoFreeForTest(p); TCMallocDoFreeForTest(p),
- "Circular loop in list detected");
- }
-}
-#endif // NDEBUG
-
-#endif
diff --git a/base/at_exit_unittest.cc b/base/at_exit_unittest.cc
deleted file mode 100644
index 3de061f..0000000
--- a/base/at_exit_unittest.cc
+++ /dev/null
@@ -1,87 +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/at_exit.h"
-#include "base/bind.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-int g_test_counter_1 = 0;
-int g_test_counter_2 = 0;
-
-void IncrementTestCounter1(void* unused) {
- ++g_test_counter_1;
-}
-
-void IncrementTestCounter2(void* unused) {
- ++g_test_counter_2;
-}
-
-void ZeroTestCounters() {
- g_test_counter_1 = 0;
- g_test_counter_2 = 0;
-}
-
-void ExpectCounter1IsZero(void* unused) {
- EXPECT_EQ(0, g_test_counter_1);
-}
-
-void ExpectParamIsNull(void* param) {
- EXPECT_EQ(nullptr, param);
-}
-
-void ExpectParamIsCounter(void* param) {
- EXPECT_EQ(&g_test_counter_1, param);
-}
-
-} // namespace
-
-class AtExitTest : public testing::Test {
- private:
- // Don't test the global AtExitManager, because asking it to process its
- // AtExit callbacks can ruin the global state that other tests may depend on.
- base::ShadowingAtExitManager exit_manager_;
-};
-
-TEST_F(AtExitTest, Basic) {
- ZeroTestCounters();
- base::AtExitManager::RegisterCallback(&IncrementTestCounter1, nullptr);
- base::AtExitManager::RegisterCallback(&IncrementTestCounter2, nullptr);
- base::AtExitManager::RegisterCallback(&IncrementTestCounter1, nullptr);
-
- EXPECT_EQ(0, g_test_counter_1);
- EXPECT_EQ(0, g_test_counter_2);
- base::AtExitManager::ProcessCallbacksNow();
- EXPECT_EQ(2, g_test_counter_1);
- EXPECT_EQ(1, g_test_counter_2);
-}
-
-TEST_F(AtExitTest, LIFOOrder) {
- ZeroTestCounters();
- base::AtExitManager::RegisterCallback(&IncrementTestCounter1, nullptr);
- base::AtExitManager::RegisterCallback(&ExpectCounter1IsZero, nullptr);
- base::AtExitManager::RegisterCallback(&IncrementTestCounter2, nullptr);
-
- EXPECT_EQ(0, g_test_counter_1);
- EXPECT_EQ(0, g_test_counter_2);
- base::AtExitManager::ProcessCallbacksNow();
- EXPECT_EQ(1, g_test_counter_1);
- EXPECT_EQ(1, g_test_counter_2);
-}
-
-TEST_F(AtExitTest, Param) {
- base::AtExitManager::RegisterCallback(&ExpectParamIsNull, nullptr);
- base::AtExitManager::RegisterCallback(&ExpectParamIsCounter,
- &g_test_counter_1);
- base::AtExitManager::ProcessCallbacksNow();
-}
-
-TEST_F(AtExitTest, Task) {
- ZeroTestCounters();
- base::AtExitManager::RegisterTask(base::Bind(&ExpectParamIsCounter,
- &g_test_counter_1));
- base::AtExitManager::ProcessCallbacksNow();
-}
diff --git a/base/atomicops_unittest.cc b/base/atomicops_unittest.cc
deleted file mode 100644
index 7298609..0000000
--- a/base/atomicops_unittest.cc
+++ /dev/null
@@ -1,248 +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/atomicops.h"
-
-#include <stdint.h>
-#include <string.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-template <class AtomicType>
-static void TestAtomicIncrement() {
- // For now, we just test single threaded execution
-
- // use a guard value to make sure the NoBarrier_AtomicIncrement doesn't go
- // outside the expected address bounds. This is in particular to
- // test that some future change to the asm code doesn't cause the
- // 32-bit NoBarrier_AtomicIncrement doesn't do the wrong thing on 64-bit
- // machines.
- struct {
- AtomicType prev_word;
- AtomicType count;
- AtomicType next_word;
- } s;
-
- AtomicType prev_word_value, next_word_value;
- memset(&prev_word_value, 0xFF, sizeof(AtomicType));
- memset(&next_word_value, 0xEE, sizeof(AtomicType));
-
- s.prev_word = prev_word_value;
- s.count = 0;
- s.next_word = next_word_value;
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 1), 1);
- EXPECT_EQ(s.count, 1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 2), 3);
- EXPECT_EQ(s.count, 3);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 3), 6);
- EXPECT_EQ(s.count, 6);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -3), 3);
- EXPECT_EQ(s.count, 3);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -2), 1);
- EXPECT_EQ(s.count, 1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), 0);
- EXPECT_EQ(s.count, 0);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -1), -1);
- EXPECT_EQ(s.count, -1);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, -4), -5);
- EXPECT_EQ(s.count, -5);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-
- EXPECT_EQ(base::subtle::NoBarrier_AtomicIncrement(&s.count, 5), 0);
- EXPECT_EQ(s.count, 0);
- EXPECT_EQ(s.prev_word, prev_word_value);
- EXPECT_EQ(s.next_word, next_word_value);
-}
-
-
-#define NUM_BITS(T) (sizeof(T) * 8)
-
-
-template <class AtomicType>
-static void TestCompareAndSwap() {
- AtomicType value = 0;
- AtomicType prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 1);
- EXPECT_EQ(1, value);
- EXPECT_EQ(0, prev);
-
- // Verify that CAS will *not* change "value" if it doesn't match the
- // expected number. CAS will always return the actual value of the
- // variable from before any change.
- AtomicType fail = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 2);
- EXPECT_EQ(1, value);
- EXPECT_EQ(1, fail);
-
- // Use test value that has non-zero bits in both halves, more for testing
- // 64-bit implementation on 32-bit platforms.
- const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 2)) + 11;
- value = k_test_val;
- prev = base::subtle::NoBarrier_CompareAndSwap(&value, 0, 5);
- EXPECT_EQ(k_test_val, value);
- EXPECT_EQ(k_test_val, prev);
-
- value = k_test_val;
- prev = base::subtle::NoBarrier_CompareAndSwap(&value, k_test_val, 5);
- EXPECT_EQ(5, value);
- EXPECT_EQ(k_test_val, prev);
-}
-
-
-template <class AtomicType>
-static void TestAtomicExchange() {
- AtomicType value = 0;
- AtomicType new_value = base::subtle::NoBarrier_AtomicExchange(&value, 1);
- EXPECT_EQ(1, value);
- EXPECT_EQ(0, new_value);
-
- // Use test value that has non-zero bits in both halves, more for testing
- // 64-bit implementation on 32-bit platforms.
- const AtomicType k_test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 2)) + 11;
- value = k_test_val;
- new_value = base::subtle::NoBarrier_AtomicExchange(&value, k_test_val);
- EXPECT_EQ(k_test_val, value);
- EXPECT_EQ(k_test_val, new_value);
-
- value = k_test_val;
- new_value = base::subtle::NoBarrier_AtomicExchange(&value, 5);
- EXPECT_EQ(5, value);
- EXPECT_EQ(k_test_val, new_value);
-}
-
-
-template <class AtomicType>
-static void TestAtomicIncrementBounds() {
- // Test at rollover boundary between int_max and int_min
- AtomicType test_val = (static_cast<uint64_t>(1) <<
- (NUM_BITS(AtomicType) - 1));
- AtomicType value = -1 ^ test_val;
- AtomicType new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
- EXPECT_EQ(test_val, value);
- EXPECT_EQ(value, new_value);
-
- base::subtle::NoBarrier_AtomicIncrement(&value, -1);
- EXPECT_EQ(-1 ^ test_val, value);
-
- // Test at 32-bit boundary for 64-bit atomic type.
- test_val = static_cast<uint64_t>(1) << (NUM_BITS(AtomicType) / 2);
- value = test_val - 1;
- new_value = base::subtle::NoBarrier_AtomicIncrement(&value, 1);
- EXPECT_EQ(test_val, value);
- EXPECT_EQ(value, new_value);
-
- base::subtle::NoBarrier_AtomicIncrement(&value, -1);
- EXPECT_EQ(test_val - 1, value);
-}
-
-// Return an AtomicType with the value 0xa5a5a5..
-template <class AtomicType>
-static AtomicType TestFillValue() {
- AtomicType val = 0;
- memset(&val, 0xa5, sizeof(AtomicType));
- return val;
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestStore() {
- const AtomicType kVal1 = TestFillValue<AtomicType>();
- const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
- AtomicType value;
-
- base::subtle::NoBarrier_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::NoBarrier_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-
- base::subtle::Acquire_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::Acquire_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-
- base::subtle::Release_Store(&value, kVal1);
- EXPECT_EQ(kVal1, value);
- base::subtle::Release_Store(&value, kVal2);
- EXPECT_EQ(kVal2, value);
-}
-
-// This is a simple sanity check that values are correct. Not testing
-// atomicity
-template <class AtomicType>
-static void TestLoad() {
- const AtomicType kVal1 = TestFillValue<AtomicType>();
- const AtomicType kVal2 = static_cast<AtomicType>(-1);
-
- AtomicType value;
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::NoBarrier_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::NoBarrier_Load(&value));
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::Acquire_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::Acquire_Load(&value));
-
- value = kVal1;
- EXPECT_EQ(kVal1, base::subtle::Release_Load(&value));
- value = kVal2;
- EXPECT_EQ(kVal2, base::subtle::Release_Load(&value));
-}
-
-TEST(AtomicOpsTest, Inc) {
- TestAtomicIncrement<base::subtle::Atomic32>();
- TestAtomicIncrement<base::subtle::AtomicWord>();
-}
-
-TEST(AtomicOpsTest, CompareAndSwap) {
- TestCompareAndSwap<base::subtle::Atomic32>();
- TestCompareAndSwap<base::subtle::AtomicWord>();
-}
-
-TEST(AtomicOpsTest, Exchange) {
- TestAtomicExchange<base::subtle::Atomic32>();
- TestAtomicExchange<base::subtle::AtomicWord>();
-}
-
-TEST(AtomicOpsTest, IncrementBounds) {
- TestAtomicIncrementBounds<base::subtle::Atomic32>();
- TestAtomicIncrementBounds<base::subtle::AtomicWord>();
-}
-
-TEST(AtomicOpsTest, Store) {
- TestStore<base::subtle::Atomic32>();
- TestStore<base::subtle::AtomicWord>();
-}
-
-TEST(AtomicOpsTest, Load) {
- TestLoad<base::subtle::Atomic32>();
- TestLoad<base::subtle::AtomicWord>();
-}
diff --git a/base/barrier_closure_unittest.cc b/base/barrier_closure_unittest.cc
deleted file mode 100644
index 819f6ac..0000000
--- 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/base64_unittest.cc b/base/base64_unittest.cc
deleted file mode 100644
index 91651f4..0000000
--- a/base/base64_unittest.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/base64.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(Base64Test, Basic) {
- const std::string kText = "hello world";
- const std::string kBase64Text = "aGVsbG8gd29ybGQ=";
-
- std::string encoded;
- std::string decoded;
- bool ok;
-
- Base64Encode(kText, &encoded);
- EXPECT_EQ(kBase64Text, encoded);
-
- ok = Base64Decode(encoded, &decoded);
- EXPECT_TRUE(ok);
- EXPECT_EQ(kText, decoded);
-}
-
-TEST(Base64Test, InPlace) {
- const std::string kText = "hello world";
- const std::string kBase64Text = "aGVsbG8gd29ybGQ=";
- std::string text(kText);
-
- Base64Encode(text, &text);
- EXPECT_EQ(kBase64Text, text);
-
- bool ok = Base64Decode(text, &text);
- EXPECT_TRUE(ok);
- EXPECT_EQ(text, kText);
-}
-
-} // namespace base
diff --git a/base/base64url_unittest.cc b/base/base64url_unittest.cc
deleted file mode 100644
index 45aa4a8..0000000
--- a/base/base64url_unittest.cc
+++ /dev/null
@@ -1,115 +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/base64url.h"
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-TEST(Base64UrlTest, EncodeIncludePaddingPolicy) {
- std::string output;
- Base64UrlEncode("hello?world", Base64UrlEncodePolicy::INCLUDE_PADDING,
- &output);
-
- // Base64 version: aGVsbG8/d29ybGQ=
- EXPECT_EQ("aGVsbG8_d29ybGQ=", output);
-
- // Test for behavior for very short and empty strings.
- Base64UrlEncode("??", Base64UrlEncodePolicy::INCLUDE_PADDING, &output);
- EXPECT_EQ("Pz8=", output);
-
- Base64UrlEncode("", Base64UrlEncodePolicy::INCLUDE_PADDING, &output);
- EXPECT_EQ("", output);
-}
-
-TEST(Base64UrlTest, EncodeOmitPaddingPolicy) {
- std::string output;
- Base64UrlEncode("hello?world", Base64UrlEncodePolicy::OMIT_PADDING, &output);
-
- // base64 version: aGVsbG8/d29ybGQ=
- EXPECT_EQ("aGVsbG8_d29ybGQ", output);
-
- // Test for behavior for very short and empty strings.
- Base64UrlEncode("??", Base64UrlEncodePolicy::OMIT_PADDING, &output);
- EXPECT_EQ("Pz8", output);
-
- Base64UrlEncode("", Base64UrlEncodePolicy::OMIT_PADDING, &output);
- EXPECT_EQ("", output);
-}
-
-TEST(Base64UrlTest, DecodeRequirePaddingPolicy) {
- std::string output;
- ASSERT_TRUE(Base64UrlDecode("aGVsbG8_d29ybGQ=",
- Base64UrlDecodePolicy::REQUIRE_PADDING, &output));
-
- EXPECT_EQ("hello?world", output);
-
- ASSERT_FALSE(Base64UrlDecode(
- "aGVsbG8_d29ybGQ", Base64UrlDecodePolicy::REQUIRE_PADDING, &output));
-
- // Test for behavior for very short and empty strings.
- ASSERT_TRUE(
- Base64UrlDecode("Pz8=", Base64UrlDecodePolicy::REQUIRE_PADDING, &output));
- EXPECT_EQ("??", output);
-
- ASSERT_TRUE(
- Base64UrlDecode("", Base64UrlDecodePolicy::REQUIRE_PADDING, &output));
- EXPECT_EQ("", output);
-}
-
-TEST(Base64UrlTest, DecodeIgnorePaddingPolicy) {
- std::string output;
- ASSERT_TRUE(Base64UrlDecode("aGVsbG8_d29ybGQ",
- Base64UrlDecodePolicy::IGNORE_PADDING, &output));
-
- EXPECT_EQ("hello?world", output);
-
- // Including the padding is accepted as well.
- ASSERT_TRUE(Base64UrlDecode("aGVsbG8_d29ybGQ=",
- Base64UrlDecodePolicy::IGNORE_PADDING, &output));
-
- EXPECT_EQ("hello?world", output);
-}
-
-TEST(Base64UrlTest, DecodeDisallowPaddingPolicy) {
- std::string output;
- ASSERT_FALSE(Base64UrlDecode(
- "aGVsbG8_d29ybGQ=", Base64UrlDecodePolicy::DISALLOW_PADDING, &output));
-
- // The policy will allow the input when padding has been omitted.
- ASSERT_TRUE(Base64UrlDecode(
- "aGVsbG8_d29ybGQ", Base64UrlDecodePolicy::DISALLOW_PADDING, &output));
-
- EXPECT_EQ("hello?world", output);
-}
-
-TEST(Base64UrlTest, DecodeDisallowsBase64Alphabet) {
- std::string output;
-
- // The "/" character is part of the conventional base64 alphabet, but has been
- // substituted with "_" in the base64url alphabet.
- ASSERT_FALSE(Base64UrlDecode(
- "aGVsbG8/d29ybGQ=", Base64UrlDecodePolicy::REQUIRE_PADDING, &output));
-}
-
-TEST(Base64UrlTest, DecodeDisallowsPaddingOnly) {
- std::string output;
-
- ASSERT_FALSE(Base64UrlDecode(
- "=", Base64UrlDecodePolicy::IGNORE_PADDING, &output));
- ASSERT_FALSE(Base64UrlDecode(
- "==", Base64UrlDecodePolicy::IGNORE_PADDING, &output));
- ASSERT_FALSE(Base64UrlDecode(
- "===", Base64UrlDecodePolicy::IGNORE_PADDING, &output));
- ASSERT_FALSE(Base64UrlDecode(
- "====", Base64UrlDecodePolicy::IGNORE_PADDING, &output));
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/big_endian_unittest.cc b/base/big_endian_unittest.cc
deleted file mode 100644
index 4e1e7ce..0000000
--- a/base/big_endian_unittest.cc
+++ /dev/null
@@ -1,116 +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/big_endian.h"
-
-#include <stdint.h>
-
-#include "base/strings/string_piece.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(BigEndianReaderTest, ReadsValues) {
- char data[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE, 0xF,
- 0x1A, 0x2B, 0x3C, 0x4D, 0x5E };
- char buf[2];
- uint8_t u8;
- uint16_t u16;
- uint32_t u32;
- uint64_t u64;
- base::StringPiece piece;
- BigEndianReader reader(data, sizeof(data));
-
- EXPECT_TRUE(reader.Skip(2));
- EXPECT_EQ(data + 2, reader.ptr());
- EXPECT_EQ(reader.remaining(), static_cast<int>(sizeof(data)) - 2);
- EXPECT_TRUE(reader.ReadBytes(buf, sizeof(buf)));
- EXPECT_EQ(0x2, buf[0]);
- EXPECT_EQ(0x3, buf[1]);
- EXPECT_TRUE(reader.ReadU8(&u8));
- EXPECT_EQ(0x4, u8);
- EXPECT_TRUE(reader.ReadU16(&u16));
- EXPECT_EQ(0x0506, u16);
- EXPECT_TRUE(reader.ReadU32(&u32));
- EXPECT_EQ(0x0708090Au, u32);
- EXPECT_TRUE(reader.ReadU64(&u64));
- EXPECT_EQ(0x0B0C0D0E0F1A2B3Cllu, u64);
- base::StringPiece expected(reader.ptr(), 2);
- EXPECT_TRUE(reader.ReadPiece(&piece, 2));
- EXPECT_EQ(2u, piece.size());
- EXPECT_EQ(expected.data(), piece.data());
-}
-
-TEST(BigEndianReaderTest, RespectsLength) {
- char data[8];
- char buf[2];
- uint8_t u8;
- uint16_t u16;
- uint32_t u32;
- uint64_t u64;
- base::StringPiece piece;
- BigEndianReader reader(data, sizeof(data));
- // 8 left
- EXPECT_FALSE(reader.Skip(9));
- EXPECT_TRUE(reader.Skip(1));
- // 7 left
- EXPECT_FALSE(reader.ReadU64(&u64));
- EXPECT_TRUE(reader.Skip(4));
- // 3 left
- EXPECT_FALSE(reader.ReadU32(&u32));
- EXPECT_FALSE(reader.ReadPiece(&piece, 4));
- EXPECT_TRUE(reader.Skip(2));
- // 1 left
- EXPECT_FALSE(reader.ReadU16(&u16));
- EXPECT_FALSE(reader.ReadBytes(buf, 2));
- EXPECT_TRUE(reader.Skip(1));
- // 0 left
- EXPECT_FALSE(reader.ReadU8(&u8));
- EXPECT_EQ(0, reader.remaining());
-}
-
-TEST(BigEndianWriterTest, WritesValues) {
- char expected[] = { 0, 0, 2, 3, 4, 5, 6, 7, 8, 9, 0xA, 0xB, 0xC, 0xD, 0xE,
- 0xF, 0x1A, 0x2B, 0x3C };
- char data[sizeof(expected)];
- char buf[] = { 0x2, 0x3 };
- memset(data, 0, sizeof(data));
- BigEndianWriter writer(data, sizeof(data));
-
- EXPECT_TRUE(writer.Skip(2));
- EXPECT_TRUE(writer.WriteBytes(buf, sizeof(buf)));
- EXPECT_TRUE(writer.WriteU8(0x4));
- EXPECT_TRUE(writer.WriteU16(0x0506));
- EXPECT_TRUE(writer.WriteU32(0x0708090A));
- EXPECT_TRUE(writer.WriteU64(0x0B0C0D0E0F1A2B3Cllu));
- EXPECT_EQ(0, memcmp(expected, data, sizeof(expected)));
-}
-
-TEST(BigEndianWriterTest, RespectsLength) {
- char data[8];
- char buf[2];
- uint8_t u8 = 0;
- uint16_t u16 = 0;
- uint32_t u32 = 0;
- uint64_t u64 = 0;
- BigEndianWriter writer(data, sizeof(data));
- // 8 left
- EXPECT_FALSE(writer.Skip(9));
- EXPECT_TRUE(writer.Skip(1));
- // 7 left
- EXPECT_FALSE(writer.WriteU64(u64));
- EXPECT_TRUE(writer.Skip(4));
- // 3 left
- EXPECT_FALSE(writer.WriteU32(u32));
- EXPECT_TRUE(writer.Skip(2));
- // 1 left
- EXPECT_FALSE(writer.WriteU16(u16));
- EXPECT_FALSE(writer.WriteBytes(buf, 2));
- EXPECT_TRUE(writer.Skip(1));
- // 0 left
- EXPECT_FALSE(writer.WriteU8(u8));
- EXPECT_EQ(0, writer.remaining());
-}
-
-} // namespace base
diff --git a/base/bind_unittest.cc b/base/bind_unittest.cc
deleted file mode 100644
index 5162a08..0000000
--- a/base/bind_unittest.cc
+++ /dev/null
@@ -1,1496 +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 <memory>
-#include <utility>
-#include <vector>
-
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/test/bind_test_util.h"
-#include "base/test/gtest_util.h"
-#include "build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::Mock;
-using ::testing::ByMove;
-using ::testing::Return;
-using ::testing::StrictMock;
-
-namespace base {
-namespace {
-
-class IncompleteType;
-
-class NoRef {
- public:
- NoRef() = default;
-
- MOCK_METHOD0(VoidMethod0, void());
- MOCK_CONST_METHOD0(VoidConstMethod0, void());
-
- MOCK_METHOD0(IntMethod0, int());
- MOCK_CONST_METHOD0(IntConstMethod0, int());
-
- MOCK_METHOD1(VoidMethodWithIntArg, void(int));
- MOCK_METHOD0(UniquePtrMethod0, std::unique_ptr<int>());
-
- private:
- // Particularly important in this test to ensure no copies are made.
- DISALLOW_COPY_AND_ASSIGN(NoRef);
-};
-
-class HasRef : public NoRef {
- public:
- HasRef() = default;
-
- MOCK_CONST_METHOD0(AddRef, void());
- MOCK_CONST_METHOD0(Release, bool());
-
- private:
- // Particularly important in this test to ensure no copies are made.
- DISALLOW_COPY_AND_ASSIGN(HasRef);
-};
-
-class HasRefPrivateDtor : public HasRef {
- private:
- ~HasRefPrivateDtor() = default;
-};
-
-static const int kParentValue = 1;
-static const int kChildValue = 2;
-
-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:
- void VirtualSet() override { value = kChildValue; }
- void NonVirtualSet() { value = kChildValue; }
-};
-
-class NoRefParent {
- public:
- virtual void VirtualSet() { value = kParentValue; }
- void NonVirtualSet() { value = kParentValue; }
- int value;
-};
-
-class NoRefChild : public NoRefParent {
- void VirtualSet() override { value = kChildValue; }
- void NonVirtualSet() { value = kChildValue; }
-};
-
-// Used for probing the number of copies and moves that occur if a type must be
-// coerced during argument forwarding in the Run() methods.
-struct DerivedCopyMoveCounter {
- DerivedCopyMoveCounter(int* copies,
- int* assigns,
- int* move_constructs,
- int* move_assigns)
- : copies_(copies),
- assigns_(assigns),
- move_constructs_(move_constructs),
- move_assigns_(move_assigns) {}
- int* copies_;
- int* assigns_;
- int* move_constructs_;
- int* move_assigns_;
-};
-
-// Used for probing the number of copies and moves in an argument.
-class CopyMoveCounter {
- public:
- CopyMoveCounter(int* copies,
- int* assigns,
- int* move_constructs,
- int* move_assigns)
- : copies_(copies),
- assigns_(assigns),
- move_constructs_(move_constructs),
- move_assigns_(move_assigns) {}
-
- CopyMoveCounter(const CopyMoveCounter& other)
- : copies_(other.copies_),
- assigns_(other.assigns_),
- move_constructs_(other.move_constructs_),
- move_assigns_(other.move_assigns_) {
- (*copies_)++;
- }
-
- CopyMoveCounter(CopyMoveCounter&& other)
- : copies_(other.copies_),
- assigns_(other.assigns_),
- move_constructs_(other.move_constructs_),
- move_assigns_(other.move_assigns_) {
- (*move_constructs_)++;
- }
-
- // Probing for copies from coercion.
- explicit CopyMoveCounter(const DerivedCopyMoveCounter& other)
- : copies_(other.copies_),
- assigns_(other.assigns_),
- move_constructs_(other.move_constructs_),
- move_assigns_(other.move_assigns_) {
- (*copies_)++;
- }
-
- // Probing for moves from coercion.
- explicit CopyMoveCounter(DerivedCopyMoveCounter&& other)
- : copies_(other.copies_),
- assigns_(other.assigns_),
- move_constructs_(other.move_constructs_),
- move_assigns_(other.move_assigns_) {
- (*move_constructs_)++;
- }
-
- const CopyMoveCounter& operator=(const CopyMoveCounter& rhs) {
- copies_ = rhs.copies_;
- assigns_ = rhs.assigns_;
- move_constructs_ = rhs.move_constructs_;
- move_assigns_ = rhs.move_assigns_;
-
- (*assigns_)++;
-
- return *this;
- }
-
- const CopyMoveCounter& operator=(CopyMoveCounter&& rhs) {
- copies_ = rhs.copies_;
- assigns_ = rhs.assigns_;
- move_constructs_ = rhs.move_constructs_;
- move_assigns_ = rhs.move_assigns_;
-
- (*move_assigns_)++;
-
- return *this;
- }
-
- int copies() const {
- return *copies_;
- }
-
- private:
- int* copies_;
- int* assigns_;
- int* move_constructs_;
- int* move_assigns_;
-};
-
-// Used for probing the number of copies in an argument. The instance is a
-// copyable and non-movable type.
-class CopyCounter {
- public:
- CopyCounter(int* copies, int* assigns)
- : counter_(copies, assigns, nullptr, nullptr) {}
- CopyCounter(const CopyCounter& other) = default;
- CopyCounter& operator=(const CopyCounter& other) = default;
-
- explicit CopyCounter(const DerivedCopyMoveCounter& other) : counter_(other) {}
-
- int copies() const { return counter_.copies(); }
-
- private:
- CopyMoveCounter counter_;
-};
-
-// Used for probing the number of moves in an argument. The instance is a
-// non-copyable and movable type.
-class MoveCounter {
- public:
- MoveCounter(int* move_constructs, int* move_assigns)
- : counter_(nullptr, nullptr, move_constructs, move_assigns) {}
- MoveCounter(MoveCounter&& other) : counter_(std::move(other.counter_)) {}
- MoveCounter& operator=(MoveCounter&& other) {
- counter_ = std::move(other.counter_);
- return *this;
- }
-
- explicit MoveCounter(DerivedCopyMoveCounter&& other)
- : counter_(std::move(other)) {}
-
- private:
- CopyMoveCounter counter_;
-};
-
-class DeleteCounter {
- public:
- explicit DeleteCounter(int* deletes)
- : deletes_(deletes) {
- }
-
- ~DeleteCounter() {
- (*deletes_)++;
- }
-
- void VoidMethod0() {}
-
- private:
- int* deletes_;
-};
-
-template <typename T>
-T PassThru(T scoper) {
- return scoper;
-}
-
-// Some test functions that we can Bind to.
-template <typename T>
-T PolymorphicIdentity(T t) {
- return t;
-}
-
-template <typename... Ts>
-struct VoidPolymorphic {
- static void Run(Ts... t) {}
-};
-
-int Identity(int n) {
- return n;
-}
-
-int ArrayGet(const int array[], int n) {
- return array[n];
-}
-
-int Sum(int a, int b, int c, int d, int e, int f) {
- return a + b + c + d + e + f;
-}
-
-const char* CStringIdentity(const char* s) {
- return s;
-}
-
-int GetCopies(const CopyMoveCounter& counter) {
- return counter.copies();
-}
-
-int UnwrapNoRefParent(NoRefParent p) {
- return p.value;
-}
-
-int UnwrapNoRefParentPtr(NoRefParent* p) {
- return p->value;
-}
-
-int UnwrapNoRefParentConstRef(const NoRefParent& p) {
- return p.value;
-}
-
-void RefArgSet(int &n) {
- n = 2;
-}
-
-void PtrArgSet(int *n) {
- *n = 2;
-}
-
-int FunctionWithWeakFirstParam(WeakPtr<NoRef> o, int n) {
- return n;
-}
-
-int FunctionWithScopedRefptrFirstParam(const scoped_refptr<HasRef>& o, int n) {
- return n;
-}
-
-void TakesACallback(const Closure& callback) {
- callback.Run();
-}
-
-int Noexcept() noexcept {
- return 42;
-}
-
-class BindTest : public ::testing::Test {
- public:
- BindTest() {
- const_has_ref_ptr_ = &has_ref_;
- const_no_ref_ptr_ = &no_ref_;
- static_func_mock_ptr = &static_func_mock_;
- }
-
- ~BindTest() override = default;
-
- static void VoidFunc0() {
- static_func_mock_ptr->VoidMethod0();
- }
-
- static int IntFunc0() { return static_func_mock_ptr->IntMethod0(); }
- int NoexceptMethod() noexcept { return 42; }
- int ConstNoexceptMethod() const noexcept { return 42; }
-
- protected:
- StrictMock<NoRef> no_ref_;
- StrictMock<HasRef> has_ref_;
- const HasRef* const_has_ref_ptr_;
- const NoRef* const_no_ref_ptr_;
- StrictMock<NoRef> static_func_mock_;
-
- // Used by the static functions to perform expectations.
- static StrictMock<NoRef>* static_func_mock_ptr;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BindTest);
-};
-
-StrictMock<NoRef>* BindTest::static_func_mock_ptr;
-StrictMock<NoRef>* g_func_mock_ptr;
-
-void VoidFunc0() {
- g_func_mock_ptr->VoidMethod0();
-}
-
-int IntFunc0() {
- return g_func_mock_ptr->IntMethod0();
-}
-
-TEST_F(BindTest, BasicTest) {
- Callback<int(int, int, int)> cb = Bind(&Sum, 32, 16, 8);
- EXPECT_EQ(92, cb.Run(13, 12, 11));
-
- Callback<int(int, int, int, int, int, int)> c1 = Bind(&Sum);
- EXPECT_EQ(69, c1.Run(14, 13, 12, 11, 10, 9));
-
- Callback<int(int, int, int)> c2 = Bind(c1, 32, 16, 8);
- EXPECT_EQ(86, c2.Run(11, 10, 9));
-
- Callback<int()> c3 = Bind(c2, 4, 2, 1);
- EXPECT_EQ(63, c3.Run());
-}
-
-// Test that currying the rvalue result of another Bind() works correctly.
-// - rvalue should be usable as argument to Bind().
-// - multiple runs of resulting Callback remain valid.
-TEST_F(BindTest, CurryingRvalueResultOfBind) {
- int n = 0;
- RepeatingClosure cb = BindRepeating(&TakesACallback,
- BindRepeating(&PtrArgSet, &n));
-
- // If we implement Bind() such that the return value has auto_ptr-like
- // semantics, the second call here will fail because ownership of
- // the internal BindState<> would have been transfered to a *temporary*
- // constructon of a Callback object on the first call.
- cb.Run();
- EXPECT_EQ(2, n);
-
- n = 0;
- cb.Run();
- EXPECT_EQ(2, n);
-}
-
-TEST_F(BindTest, RepeatingCallbackBasicTest) {
- RepeatingCallback<int(int)> c0 = BindRepeating(&Sum, 1, 2, 4, 8, 16);
-
- // RepeatingCallback can run via a lvalue-reference.
- EXPECT_EQ(63, c0.Run(32));
-
- // It is valid to call a RepeatingCallback more than once.
- EXPECT_EQ(54, c0.Run(23));
-
- // BindRepeating can handle a RepeatingCallback as the target functor.
- RepeatingCallback<int()> c1 = BindRepeating(c0, 11);
-
- // RepeatingCallback can run via a rvalue-reference.
- EXPECT_EQ(42, std::move(c1).Run());
-
- // BindRepeating can handle a rvalue-reference of RepeatingCallback.
- EXPECT_EQ(32, BindRepeating(std::move(c0), 1).Run());
-}
-
-TEST_F(BindTest, OnceCallbackBasicTest) {
- OnceCallback<int(int)> c0 = BindOnce(&Sum, 1, 2, 4, 8, 16);
-
- // OnceCallback can run via a rvalue-reference.
- EXPECT_EQ(63, std::move(c0).Run(32));
-
- // After running via the rvalue-reference, the value of the OnceCallback
- // is undefined. The implementation simply clears the instance after the
- // invocation.
- EXPECT_TRUE(c0.is_null());
-
- c0 = BindOnce(&Sum, 2, 3, 5, 7, 11);
-
- // BindOnce can handle a rvalue-reference of OnceCallback as the target
- // functor.
- OnceCallback<int()> c1 = BindOnce(std::move(c0), 13);
- EXPECT_EQ(41, std::move(c1).Run());
-
- RepeatingCallback<int(int)> c2 = BindRepeating(&Sum, 2, 3, 5, 7, 11);
- EXPECT_EQ(41, BindOnce(c2, 13).Run());
-}
-
-// IgnoreResult adapter test.
-// - Function with return value.
-// - Method with return value.
-// - Const Method with return.
-// - Method with return value bound to WeakPtr<>.
-// - Const Method with return bound to WeakPtr<>.
-TEST_F(BindTest, IgnoreResultForRepeating) {
- EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
- EXPECT_CALL(has_ref_, AddRef()).Times(2);
- EXPECT_CALL(has_ref_, Release()).Times(2);
- EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
- EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
- EXPECT_CALL(no_ref_, IntMethod0()).WillOnce(Return(12));
- EXPECT_CALL(no_ref_, IntConstMethod0()).WillOnce(Return(13));
-
- RepeatingClosure normal_func_cb = BindRepeating(IgnoreResult(&IntFunc0));
- normal_func_cb.Run();
-
- RepeatingClosure non_void_method_cb =
- BindRepeating(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
- non_void_method_cb.Run();
-
- RepeatingClosure non_void_const_method_cb =
- BindRepeating(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
- non_void_const_method_cb.Run();
-
- WeakPtrFactory<NoRef> weak_factory(&no_ref_);
- WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
-
- RepeatingClosure non_void_weak_method_cb =
- BindRepeating(IgnoreResult(&NoRef::IntMethod0),
- weak_factory.GetWeakPtr());
- non_void_weak_method_cb.Run();
-
- RepeatingClosure non_void_weak_const_method_cb =
- BindRepeating(IgnoreResult(&NoRef::IntConstMethod0),
- weak_factory.GetWeakPtr());
- non_void_weak_const_method_cb.Run();
-
- weak_factory.InvalidateWeakPtrs();
- non_void_weak_const_method_cb.Run();
- non_void_weak_method_cb.Run();
-}
-
-TEST_F(BindTest, IgnoreResultForOnce) {
- EXPECT_CALL(static_func_mock_, IntMethod0()).WillOnce(Return(1337));
- EXPECT_CALL(has_ref_, AddRef()).Times(2);
- EXPECT_CALL(has_ref_, Release()).Times(2);
- EXPECT_CALL(has_ref_, IntMethod0()).WillOnce(Return(10));
- EXPECT_CALL(has_ref_, IntConstMethod0()).WillOnce(Return(11));
-
- OnceClosure normal_func_cb = BindOnce(IgnoreResult(&IntFunc0));
- std::move(normal_func_cb).Run();
-
- OnceClosure non_void_method_cb =
- BindOnce(IgnoreResult(&HasRef::IntMethod0), &has_ref_);
- std::move(non_void_method_cb).Run();
-
- OnceClosure non_void_const_method_cb =
- BindOnce(IgnoreResult(&HasRef::IntConstMethod0), &has_ref_);
- std::move(non_void_const_method_cb).Run();
-
- WeakPtrFactory<NoRef> weak_factory(&no_ref_);
- WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
-
- OnceClosure non_void_weak_method_cb =
- BindOnce(IgnoreResult(&NoRef::IntMethod0),
- weak_factory.GetWeakPtr());
- OnceClosure non_void_weak_const_method_cb =
- BindOnce(IgnoreResult(&NoRef::IntConstMethod0),
- weak_factory.GetWeakPtr());
-
- weak_factory.InvalidateWeakPtrs();
- std::move(non_void_weak_const_method_cb).Run();
- std::move(non_void_weak_method_cb).Run();
-}
-
-// Functions that take reference parameters.
-// - Forced reference parameter type still stores a copy.
-// - Forced const reference parameter type still stores a copy.
-TEST_F(BindTest, ReferenceArgumentBindingForRepeating) {
- int n = 1;
- int& ref_n = n;
- const int& const_ref_n = n;
-
- RepeatingCallback<int()> ref_copies_cb = BindRepeating(&Identity, ref_n);
- EXPECT_EQ(n, ref_copies_cb.Run());
- n++;
- EXPECT_EQ(n - 1, ref_copies_cb.Run());
-
- RepeatingCallback<int()> const_ref_copies_cb =
- BindRepeating(&Identity, const_ref_n);
- EXPECT_EQ(n, const_ref_copies_cb.Run());
- n++;
- EXPECT_EQ(n - 1, const_ref_copies_cb.Run());
-}
-
-TEST_F(BindTest, ReferenceArgumentBindingForOnce) {
- int n = 1;
- int& ref_n = n;
- const int& const_ref_n = n;
-
- OnceCallback<int()> ref_copies_cb = BindOnce(&Identity, ref_n);
- n++;
- EXPECT_EQ(n - 1, std::move(ref_copies_cb).Run());
-
- OnceCallback<int()> const_ref_copies_cb =
- BindOnce(&Identity, const_ref_n);
- n++;
- EXPECT_EQ(n - 1, std::move(const_ref_copies_cb).Run());
-}
-
-// Check that we can pass in arrays and have them be stored as a pointer.
-// - Array of values stores a pointer.
-// - Array of const values stores a pointer.
-TEST_F(BindTest, ArrayArgumentBindingForRepeating) {
- int array[4] = {1, 1, 1, 1};
- const int (*const_array_ptr)[4] = &array;
-
- RepeatingCallback<int()> array_cb = BindRepeating(&ArrayGet, array, 1);
- EXPECT_EQ(1, array_cb.Run());
-
- RepeatingCallback<int()> const_array_cb =
- BindRepeating(&ArrayGet, *const_array_ptr, 1);
- EXPECT_EQ(1, const_array_cb.Run());
-
- array[1] = 3;
- EXPECT_EQ(3, array_cb.Run());
- EXPECT_EQ(3, const_array_cb.Run());
-}
-
-TEST_F(BindTest, ArrayArgumentBindingForOnce) {
- int array[4] = {1, 1, 1, 1};
- const int (*const_array_ptr)[4] = &array;
-
- OnceCallback<int()> array_cb = BindOnce(&ArrayGet, array, 1);
- OnceCallback<int()> const_array_cb =
- BindOnce(&ArrayGet, *const_array_ptr, 1);
-
- array[1] = 3;
- EXPECT_EQ(3, std::move(array_cb).Run());
- EXPECT_EQ(3, std::move(const_array_cb).Run());
-}
-
-// WeakPtr() support.
-// - Method bound to WeakPtr<> to non-const object.
-// - Const method bound to WeakPtr<> to non-const object.
-// - Const method bound to WeakPtr<> to const object.
-// - Normal Function with WeakPtr<> as P1 can have return type and is
-// not canceled.
-TEST_F(BindTest, WeakPtrForRepeating) {
- EXPECT_CALL(no_ref_, VoidMethod0());
- EXPECT_CALL(no_ref_, VoidConstMethod0()).Times(2);
-
- WeakPtrFactory<NoRef> weak_factory(&no_ref_);
- WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
-
- RepeatingClosure method_cb =
- BindRepeating(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
- method_cb.Run();
-
- RepeatingClosure const_method_cb =
- BindRepeating(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
- const_method_cb.Run();
-
- RepeatingClosure const_method_const_ptr_cb =
- BindRepeating(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
- const_method_const_ptr_cb.Run();
-
- RepeatingCallback<int(int)> normal_func_cb =
- BindRepeating(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
- EXPECT_EQ(1, normal_func_cb.Run(1));
-
- weak_factory.InvalidateWeakPtrs();
- const_weak_factory.InvalidateWeakPtrs();
-
- method_cb.Run();
- const_method_cb.Run();
- const_method_const_ptr_cb.Run();
-
- // Still runs even after the pointers are invalidated.
- EXPECT_EQ(2, normal_func_cb.Run(2));
-}
-
-TEST_F(BindTest, WeakPtrForOnce) {
- WeakPtrFactory<NoRef> weak_factory(&no_ref_);
- WeakPtrFactory<const NoRef> const_weak_factory(const_no_ref_ptr_);
-
- OnceClosure method_cb =
- BindOnce(&NoRef::VoidMethod0, weak_factory.GetWeakPtr());
- OnceClosure const_method_cb =
- BindOnce(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
- OnceClosure const_method_const_ptr_cb =
- BindOnce(&NoRef::VoidConstMethod0, const_weak_factory.GetWeakPtr());
- Callback<int(int)> normal_func_cb =
- Bind(&FunctionWithWeakFirstParam, weak_factory.GetWeakPtr());
-
- weak_factory.InvalidateWeakPtrs();
- const_weak_factory.InvalidateWeakPtrs();
-
- std::move(method_cb).Run();
- std::move(const_method_cb).Run();
- std::move(const_method_const_ptr_cb).Run();
-
- // Still runs even after the pointers are invalidated.
- EXPECT_EQ(2, std::move(normal_func_cb).Run(2));
-}
-
-// ConstRef() wrapper support.
-// - Binding w/o ConstRef takes a copy.
-// - Binding a ConstRef takes a reference.
-// - Binding ConstRef to a function ConstRef does not copy on invoke.
-TEST_F(BindTest, ConstRefForRepeating) {
- int n = 1;
-
- RepeatingCallback<int()> copy_cb = BindRepeating(&Identity, n);
- RepeatingCallback<int()> const_ref_cb = BindRepeating(&Identity, ConstRef(n));
- EXPECT_EQ(n, copy_cb.Run());
- EXPECT_EQ(n, const_ref_cb.Run());
- n++;
- EXPECT_EQ(n - 1, copy_cb.Run());
- EXPECT_EQ(n, const_ref_cb.Run());
-
- int copies = 0;
- int assigns = 0;
- int move_constructs = 0;
- int move_assigns = 0;
- CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
- RepeatingCallback<int()> all_const_ref_cb =
- BindRepeating(&GetCopies, ConstRef(counter));
- EXPECT_EQ(0, all_const_ref_cb.Run());
- EXPECT_EQ(0, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(0, move_constructs);
- EXPECT_EQ(0, move_assigns);
-}
-
-TEST_F(BindTest, ConstRefForOnce) {
- int n = 1;
-
- OnceCallback<int()> copy_cb = BindOnce(&Identity, n);
- OnceCallback<int()> const_ref_cb = BindOnce(&Identity, ConstRef(n));
- n++;
- EXPECT_EQ(n - 1, std::move(copy_cb).Run());
- EXPECT_EQ(n, std::move(const_ref_cb).Run());
-
- int copies = 0;
- int assigns = 0;
- int move_constructs = 0;
- int move_assigns = 0;
- CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
- OnceCallback<int()> all_const_ref_cb =
- BindOnce(&GetCopies, ConstRef(counter));
- EXPECT_EQ(0, std::move(all_const_ref_cb).Run());
- EXPECT_EQ(0, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(0, move_constructs);
- EXPECT_EQ(0, move_assigns);
-}
-
-// Test Owned() support.
-TEST_F(BindTest, OwnedForRepeating) {
- int deletes = 0;
- DeleteCounter* counter = new DeleteCounter(&deletes);
-
- // If we don't capture, delete happens on Callback destruction/reset.
- // return the same value.
- RepeatingCallback<DeleteCounter*()> no_capture_cb =
- BindRepeating(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
- ASSERT_EQ(counter, no_capture_cb.Run());
- ASSERT_EQ(counter, no_capture_cb.Run());
- EXPECT_EQ(0, deletes);
- no_capture_cb.Reset(); // This should trigger a delete.
- EXPECT_EQ(1, deletes);
-
- deletes = 0;
- counter = new DeleteCounter(&deletes);
- RepeatingClosure own_object_cb =
- BindRepeating(&DeleteCounter::VoidMethod0, Owned(counter));
- own_object_cb.Run();
- EXPECT_EQ(0, deletes);
- own_object_cb.Reset();
- EXPECT_EQ(1, deletes);
-}
-
-TEST_F(BindTest, OwnedForOnce) {
- int deletes = 0;
- DeleteCounter* counter = new DeleteCounter(&deletes);
-
- // If we don't capture, delete happens on Callback destruction/reset.
- // return the same value.
- OnceCallback<DeleteCounter*()> no_capture_cb =
- BindOnce(&PolymorphicIdentity<DeleteCounter*>, Owned(counter));
- EXPECT_EQ(0, deletes);
- no_capture_cb.Reset(); // This should trigger a delete.
- EXPECT_EQ(1, deletes);
-
- deletes = 0;
- counter = new DeleteCounter(&deletes);
- OnceClosure own_object_cb =
- BindOnce(&DeleteCounter::VoidMethod0, Owned(counter));
- EXPECT_EQ(0, deletes);
- own_object_cb.Reset();
- EXPECT_EQ(1, deletes);
-}
-
-template <typename T>
-class BindVariantsTest : public ::testing::Test {
-};
-
-struct RepeatingTestConfig {
- template <typename Signature>
- using CallbackType = RepeatingCallback<Signature>;
- using ClosureType = RepeatingClosure;
-
- template <typename F, typename... Args>
- static CallbackType<MakeUnboundRunType<F, Args...>>
- Bind(F&& f, Args&&... args) {
- return BindRepeating(std::forward<F>(f), std::forward<Args>(args)...);
- }
-};
-
-struct OnceTestConfig {
- template <typename Signature>
- using CallbackType = OnceCallback<Signature>;
- using ClosureType = OnceClosure;
-
- template <typename F, typename... Args>
- static CallbackType<MakeUnboundRunType<F, Args...>>
- Bind(F&& f, Args&&... args) {
- return BindOnce(std::forward<F>(f), std::forward<Args>(args)...);
- }
-};
-
-using BindVariantsTestConfig = ::testing::Types<
- RepeatingTestConfig, OnceTestConfig>;
-TYPED_TEST_CASE(BindVariantsTest, BindVariantsTestConfig);
-
-template <typename TypeParam, typename Signature>
-using CallbackType = typename TypeParam::template CallbackType<Signature>;
-
-// Function type support.
-// - Normal function.
-// - Normal function bound with non-refcounted first argument.
-// - Method bound to non-const object.
-// - Method bound to scoped_refptr.
-// - Const method bound to non-const object.
-// - Const method bound to const object.
-// - Derived classes can be used with pointers to non-virtual base functions.
-// - Derived classes can be used with pointers to virtual base functions (and
-// preserve virtual dispatch).
-TYPED_TEST(BindVariantsTest, FunctionTypeSupport) {
- using ClosureType = typename TypeParam::ClosureType;
-
- StrictMock<HasRef> has_ref;
- StrictMock<NoRef> no_ref;
- StrictMock<NoRef> static_func_mock;
- const HasRef* const_has_ref_ptr = &has_ref;
- g_func_mock_ptr = &static_func_mock;
-
- EXPECT_CALL(static_func_mock, VoidMethod0());
- EXPECT_CALL(has_ref, AddRef()).Times(4);
- EXPECT_CALL(has_ref, Release()).Times(4);
- EXPECT_CALL(has_ref, VoidMethod0()).Times(2);
- EXPECT_CALL(has_ref, VoidConstMethod0()).Times(2);
-
- ClosureType normal_cb = TypeParam::Bind(&VoidFunc0);
- CallbackType<TypeParam, NoRef*()> normal_non_refcounted_cb =
- TypeParam::Bind(&PolymorphicIdentity<NoRef*>, &no_ref);
- std::move(normal_cb).Run();
- EXPECT_EQ(&no_ref, std::move(normal_non_refcounted_cb).Run());
-
- ClosureType method_cb = TypeParam::Bind(&HasRef::VoidMethod0, &has_ref);
- ClosureType method_refptr_cb =
- TypeParam::Bind(&HasRef::VoidMethod0, WrapRefCounted(&has_ref));
- ClosureType const_method_nonconst_obj_cb =
- TypeParam::Bind(&HasRef::VoidConstMethod0, &has_ref);
- ClosureType const_method_const_obj_cb =
- TypeParam::Bind(&HasRef::VoidConstMethod0, const_has_ref_ptr);
- std::move(method_cb).Run();
- std::move(method_refptr_cb).Run();
- std::move(const_method_nonconst_obj_cb).Run();
- std::move(const_method_const_obj_cb).Run();
-
- Child child;
- child.value = 0;
- ClosureType virtual_set_cb = TypeParam::Bind(&Parent::VirtualSet, &child);
- std::move(virtual_set_cb).Run();
- EXPECT_EQ(kChildValue, child.value);
-
- child.value = 0;
- ClosureType non_virtual_set_cb =
- TypeParam::Bind(&Parent::NonVirtualSet, &child);
- std::move(non_virtual_set_cb).Run();
- EXPECT_EQ(kParentValue, child.value);
-}
-
-// Return value support.
-// - Function with return value.
-// - Method with return value.
-// - Const method with return value.
-// - Move-only return value.
-TYPED_TEST(BindVariantsTest, ReturnValues) {
- StrictMock<NoRef> static_func_mock;
- StrictMock<HasRef> has_ref;
- g_func_mock_ptr = &static_func_mock;
- const HasRef* const_has_ref_ptr = &has_ref;
-
- EXPECT_CALL(static_func_mock, IntMethod0()).WillOnce(Return(1337));
- EXPECT_CALL(has_ref, AddRef()).Times(4);
- EXPECT_CALL(has_ref, Release()).Times(4);
- EXPECT_CALL(has_ref, IntMethod0()).WillOnce(Return(31337));
- EXPECT_CALL(has_ref, IntConstMethod0())
- .WillOnce(Return(41337))
- .WillOnce(Return(51337));
- EXPECT_CALL(has_ref, UniquePtrMethod0())
- .WillOnce(Return(ByMove(std::make_unique<int>(42))));
-
- CallbackType<TypeParam, int()> normal_cb = TypeParam::Bind(&IntFunc0);
- CallbackType<TypeParam, int()> method_cb =
- TypeParam::Bind(&HasRef::IntMethod0, &has_ref);
- CallbackType<TypeParam, int()> const_method_nonconst_obj_cb =
- TypeParam::Bind(&HasRef::IntConstMethod0, &has_ref);
- CallbackType<TypeParam, int()> const_method_const_obj_cb =
- TypeParam::Bind(&HasRef::IntConstMethod0, const_has_ref_ptr);
- CallbackType<TypeParam, std::unique_ptr<int>()> move_only_rv_cb =
- TypeParam::Bind(&HasRef::UniquePtrMethod0, &has_ref);
- EXPECT_EQ(1337, std::move(normal_cb).Run());
- EXPECT_EQ(31337, std::move(method_cb).Run());
- EXPECT_EQ(41337, std::move(const_method_nonconst_obj_cb).Run());
- EXPECT_EQ(51337, std::move(const_method_const_obj_cb).Run());
- EXPECT_EQ(42, *std::move(move_only_rv_cb).Run());
-}
-
-// Argument binding tests.
-// - Argument binding to primitive.
-// - Argument binding to primitive pointer.
-// - Argument binding to a literal integer.
-// - Argument binding to a literal string.
-// - Argument binding with template function.
-// - Argument binding to an object.
-// - Argument binding to pointer to incomplete type.
-// - Argument gets type converted.
-// - Pointer argument gets converted.
-// - Const Reference forces conversion.
-TYPED_TEST(BindVariantsTest, ArgumentBinding) {
- int n = 2;
-
- EXPECT_EQ(n, TypeParam::Bind(&Identity, n).Run());
- EXPECT_EQ(&n, TypeParam::Bind(&PolymorphicIdentity<int*>, &n).Run());
- EXPECT_EQ(3, TypeParam::Bind(&Identity, 3).Run());
- EXPECT_STREQ("hi", TypeParam::Bind(&CStringIdentity, "hi").Run());
- EXPECT_EQ(4, TypeParam::Bind(&PolymorphicIdentity<int>, 4).Run());
-
- NoRefParent p;
- p.value = 5;
- EXPECT_EQ(5, TypeParam::Bind(&UnwrapNoRefParent, p).Run());
-
- IncompleteType* incomplete_ptr = reinterpret_cast<IncompleteType*>(123);
- EXPECT_EQ(incomplete_ptr,
- TypeParam::Bind(&PolymorphicIdentity<IncompleteType*>,
- incomplete_ptr).Run());
-
- NoRefChild c;
- c.value = 6;
- EXPECT_EQ(6, TypeParam::Bind(&UnwrapNoRefParent, c).Run());
-
- c.value = 7;
- EXPECT_EQ(7, TypeParam::Bind(&UnwrapNoRefParentPtr, &c).Run());
-
- c.value = 8;
- EXPECT_EQ(8, TypeParam::Bind(&UnwrapNoRefParentConstRef, c).Run());
-}
-
-// Unbound argument type support tests.
-// - Unbound value.
-// - Unbound pointer.
-// - Unbound reference.
-// - Unbound const reference.
-// - Unbound unsized array.
-// - Unbound sized array.
-// - Unbound array-of-arrays.
-TYPED_TEST(BindVariantsTest, UnboundArgumentTypeSupport) {
- CallbackType<TypeParam, void(int)> unbound_value_cb =
- TypeParam::Bind(&VoidPolymorphic<int>::Run);
- CallbackType<TypeParam, void(int*)> unbound_pointer_cb =
- TypeParam::Bind(&VoidPolymorphic<int*>::Run);
- CallbackType<TypeParam, void(int&)> unbound_ref_cb =
- TypeParam::Bind(&VoidPolymorphic<int&>::Run);
- CallbackType<TypeParam, void(const int&)> unbound_const_ref_cb =
- TypeParam::Bind(&VoidPolymorphic<const int&>::Run);
- CallbackType<TypeParam, void(int[])> unbound_unsized_array_cb =
- TypeParam::Bind(&VoidPolymorphic<int[]>::Run);
- CallbackType<TypeParam, void(int[2])> unbound_sized_array_cb =
- TypeParam::Bind(&VoidPolymorphic<int[2]>::Run);
- CallbackType<TypeParam, void(int[][2])> unbound_array_of_arrays_cb =
- TypeParam::Bind(&VoidPolymorphic<int[][2]>::Run);
- CallbackType<TypeParam, void(int&)> unbound_ref_with_bound_arg =
- TypeParam::Bind(&VoidPolymorphic<int, int&>::Run, 1);
-}
-
-// Function with unbound reference parameter.
-// - Original parameter is modified by callback.
-TYPED_TEST(BindVariantsTest, UnboundReferenceSupport) {
- int n = 0;
- CallbackType<TypeParam, void(int&)> unbound_ref_cb =
- TypeParam::Bind(&RefArgSet);
- std::move(unbound_ref_cb).Run(n);
- EXPECT_EQ(2, n);
-}
-
-// Unretained() wrapper support.
-// - Method bound to Unretained() non-const object.
-// - Const method bound to Unretained() non-const object.
-// - Const method bound to Unretained() const object.
-TYPED_TEST(BindVariantsTest, Unretained) {
- StrictMock<NoRef> no_ref;
- const NoRef* const_no_ref_ptr = &no_ref;
-
- EXPECT_CALL(no_ref, VoidMethod0());
- EXPECT_CALL(no_ref, VoidConstMethod0()).Times(2);
-
- TypeParam::Bind(&NoRef::VoidMethod0, Unretained(&no_ref)).Run();
- TypeParam::Bind(&NoRef::VoidConstMethod0, Unretained(&no_ref)).Run();
- TypeParam::Bind(&NoRef::VoidConstMethod0, Unretained(const_no_ref_ptr)).Run();
-}
-
-TYPED_TEST(BindVariantsTest, ScopedRefptr) {
- StrictMock<HasRef> has_ref;
- EXPECT_CALL(has_ref, AddRef()).Times(1);
- EXPECT_CALL(has_ref, Release()).Times(1);
-
- const scoped_refptr<HasRef> refptr(&has_ref);
- CallbackType<TypeParam, int()> scoped_refptr_const_ref_cb =
- TypeParam::Bind(&FunctionWithScopedRefptrFirstParam,
- base::ConstRef(refptr), 1);
- EXPECT_EQ(1, std::move(scoped_refptr_const_ref_cb).Run());
-}
-
-TYPED_TEST(BindVariantsTest, UniquePtrReceiver) {
- std::unique_ptr<StrictMock<NoRef>> no_ref(new StrictMock<NoRef>);
- EXPECT_CALL(*no_ref, VoidMethod0()).Times(1);
- TypeParam::Bind(&NoRef::VoidMethod0, std::move(no_ref)).Run();
-}
-
-// Tests for Passed() wrapper support:
-// - Passed() can be constructed from a pointer to scoper.
-// - Passed() can be constructed from a scoper rvalue.
-// - Using Passed() gives Callback Ownership.
-// - Ownership is transferred from Callback to callee on the first Run().
-// - Callback supports unbound arguments.
-template <typename T>
-class BindMoveOnlyTypeTest : public ::testing::Test {
-};
-
-struct CustomDeleter {
- void operator()(DeleteCounter* c) { delete c; }
-};
-
-using MoveOnlyTypesToTest =
- ::testing::Types<std::unique_ptr<DeleteCounter>,
- std::unique_ptr<DeleteCounter, CustomDeleter>>;
-TYPED_TEST_CASE(BindMoveOnlyTypeTest, MoveOnlyTypesToTest);
-
-TYPED_TEST(BindMoveOnlyTypeTest, PassedToBoundCallback) {
- int deletes = 0;
-
- TypeParam ptr(new DeleteCounter(&deletes));
- Callback<TypeParam()> callback = Bind(&PassThru<TypeParam>, Passed(&ptr));
- EXPECT_FALSE(ptr.get());
- EXPECT_EQ(0, deletes);
-
- // If we never invoke the Callback, it retains ownership and deletes.
- callback.Reset();
- EXPECT_EQ(1, deletes);
-}
-
-TYPED_TEST(BindMoveOnlyTypeTest, PassedWithRvalue) {
- int deletes = 0;
- Callback<TypeParam()> callback = Bind(
- &PassThru<TypeParam>, Passed(TypeParam(new DeleteCounter(&deletes))));
- EXPECT_EQ(0, deletes);
-
- // If we never invoke the Callback, it retains ownership and deletes.
- callback.Reset();
- EXPECT_EQ(1, deletes);
-}
-
-// Check that ownership can be transferred back out.
-TYPED_TEST(BindMoveOnlyTypeTest, ReturnMoveOnlyType) {
- int deletes = 0;
- DeleteCounter* counter = new DeleteCounter(&deletes);
- Callback<TypeParam()> callback =
- Bind(&PassThru<TypeParam>, Passed(TypeParam(counter)));
- TypeParam result = callback.Run();
- ASSERT_EQ(counter, result.get());
- EXPECT_EQ(0, deletes);
-
- // Resetting does not delete since ownership was transferred.
- callback.Reset();
- EXPECT_EQ(0, deletes);
-
- // Ensure that we actually did get ownership.
- result.reset();
- EXPECT_EQ(1, deletes);
-}
-
-TYPED_TEST(BindMoveOnlyTypeTest, UnboundForwarding) {
- int deletes = 0;
- TypeParam ptr(new DeleteCounter(&deletes));
- // Test unbound argument forwarding.
- Callback<TypeParam(TypeParam)> cb_unbound = Bind(&PassThru<TypeParam>);
- cb_unbound.Run(std::move(ptr));
- EXPECT_EQ(1, deletes);
-}
-
-void VerifyVector(const std::vector<std::unique_ptr<int>>& v) {
- ASSERT_EQ(1u, v.size());
- EXPECT_EQ(12345, *v[0]);
-}
-
-std::vector<std::unique_ptr<int>> AcceptAndReturnMoveOnlyVector(
- std::vector<std::unique_ptr<int>> v) {
- VerifyVector(v);
- return v;
-}
-
-// Test that a vector containing move-only types can be used with Callback.
-TEST_F(BindTest, BindMoveOnlyVector) {
- using MoveOnlyVector = std::vector<std::unique_ptr<int>>;
-
- MoveOnlyVector v;
- v.push_back(WrapUnique(new int(12345)));
-
- // Early binding should work:
- base::Callback<MoveOnlyVector()> bound_cb =
- base::Bind(&AcceptAndReturnMoveOnlyVector, Passed(&v));
- MoveOnlyVector intermediate_result = bound_cb.Run();
- VerifyVector(intermediate_result);
-
- // As should passing it as an argument to Run():
- base::Callback<MoveOnlyVector(MoveOnlyVector)> unbound_cb =
- base::Bind(&AcceptAndReturnMoveOnlyVector);
- MoveOnlyVector final_result = unbound_cb.Run(std::move(intermediate_result));
- VerifyVector(final_result);
-}
-
-// Argument copy-constructor usage for non-reference copy-only parameters.
-// - Bound arguments are only copied once.
-// - Forwarded arguments are only copied once.
-// - Forwarded arguments with coercions are only copied twice (once for the
-// coercion, and one for the final dispatch).
-TEST_F(BindTest, ArgumentCopies) {
- int copies = 0;
- int assigns = 0;
-
- CopyCounter counter(&copies, &assigns);
- Bind(&VoidPolymorphic<CopyCounter>::Run, counter);
- EXPECT_EQ(1, copies);
- EXPECT_EQ(0, assigns);
-
- copies = 0;
- assigns = 0;
- Bind(&VoidPolymorphic<CopyCounter>::Run, CopyCounter(&copies, &assigns));
- EXPECT_EQ(1, copies);
- EXPECT_EQ(0, assigns);
-
- copies = 0;
- assigns = 0;
- Bind(&VoidPolymorphic<CopyCounter>::Run).Run(counter);
- EXPECT_EQ(2, copies);
- EXPECT_EQ(0, assigns);
-
- copies = 0;
- assigns = 0;
- Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(&copies, &assigns));
- EXPECT_EQ(1, copies);
- EXPECT_EQ(0, assigns);
-
- copies = 0;
- assigns = 0;
- DerivedCopyMoveCounter derived(&copies, &assigns, nullptr, nullptr);
- Bind(&VoidPolymorphic<CopyCounter>::Run).Run(CopyCounter(derived));
- EXPECT_EQ(2, copies);
- EXPECT_EQ(0, assigns);
-
- copies = 0;
- assigns = 0;
- Bind(&VoidPolymorphic<CopyCounter>::Run)
- .Run(CopyCounter(
- DerivedCopyMoveCounter(&copies, &assigns, nullptr, nullptr)));
- EXPECT_EQ(2, copies);
- EXPECT_EQ(0, assigns);
-}
-
-// Argument move-constructor usage for move-only parameters.
-// - Bound arguments passed by move are not copied.
-TEST_F(BindTest, ArgumentMoves) {
- int move_constructs = 0;
- int move_assigns = 0;
-
- Bind(&VoidPolymorphic<const MoveCounter&>::Run,
- MoveCounter(&move_constructs, &move_assigns));
- EXPECT_EQ(1, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- // TODO(tzik): Support binding move-only type into a non-reference parameter
- // of a variant of Callback.
-
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<MoveCounter>::Run)
- .Run(MoveCounter(&move_constructs, &move_assigns));
- EXPECT_EQ(1, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<MoveCounter>::Run)
- .Run(MoveCounter(DerivedCopyMoveCounter(
- nullptr, nullptr, &move_constructs, &move_assigns)));
- EXPECT_EQ(2, move_constructs);
- EXPECT_EQ(0, move_assigns);
-}
-
-// Argument constructor usage for non-reference movable-copyable
-// parameters.
-// - Bound arguments passed by move are not copied.
-// - Forwarded arguments are only copied once.
-// - Forwarded arguments with coercions are only copied once and moved once.
-TEST_F(BindTest, ArgumentCopiesAndMoves) {
- int copies = 0;
- int assigns = 0;
- int move_constructs = 0;
- int move_assigns = 0;
-
- CopyMoveCounter counter(&copies, &assigns, &move_constructs, &move_assigns);
- Bind(&VoidPolymorphic<CopyMoveCounter>::Run, counter);
- EXPECT_EQ(1, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(0, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- copies = 0;
- assigns = 0;
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<CopyMoveCounter>::Run,
- CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
- EXPECT_EQ(0, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(1, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- copies = 0;
- assigns = 0;
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<CopyMoveCounter>::Run).Run(counter);
- EXPECT_EQ(1, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(1, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- copies = 0;
- assigns = 0;
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
- .Run(CopyMoveCounter(&copies, &assigns, &move_constructs, &move_assigns));
- EXPECT_EQ(0, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(1, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- DerivedCopyMoveCounter derived_counter(&copies, &assigns, &move_constructs,
- &move_assigns);
- copies = 0;
- assigns = 0;
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
- .Run(CopyMoveCounter(derived_counter));
- EXPECT_EQ(1, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(1, move_constructs);
- EXPECT_EQ(0, move_assigns);
-
- copies = 0;
- assigns = 0;
- move_constructs = 0;
- move_assigns = 0;
- Bind(&VoidPolymorphic<CopyMoveCounter>::Run)
- .Run(CopyMoveCounter(DerivedCopyMoveCounter(
- &copies, &assigns, &move_constructs, &move_assigns)));
- EXPECT_EQ(0, copies);
- EXPECT_EQ(0, assigns);
- EXPECT_EQ(2, move_constructs);
- EXPECT_EQ(0, move_assigns);
-}
-
-TEST_F(BindTest, CapturelessLambda) {
- EXPECT_FALSE(internal::IsCallableObject<void>::value);
- EXPECT_FALSE(internal::IsCallableObject<int>::value);
- EXPECT_FALSE(internal::IsCallableObject<void (*)()>::value);
- EXPECT_FALSE(internal::IsCallableObject<void (NoRef::*)()>::value);
-
- auto f = []() {};
- EXPECT_TRUE(internal::IsCallableObject<decltype(f)>::value);
-
- int i = 0;
- auto g = [i]() { (void)i; };
- EXPECT_TRUE(internal::IsCallableObject<decltype(g)>::value);
-
- auto h = [](int, double) { return 'k'; };
- EXPECT_TRUE((std::is_same<
- char(int, double),
- internal::ExtractCallableRunType<decltype(h)>>::value));
-
- EXPECT_EQ(42, Bind([] { return 42; }).Run());
- EXPECT_EQ(42, Bind([](int i) { return i * 7; }, 6).Run());
-
- int x = 1;
- base::Callback<void(int)> cb =
- Bind([](int* x, int i) { *x *= i; }, Unretained(&x));
- cb.Run(6);
- EXPECT_EQ(6, x);
- cb.Run(7);
- EXPECT_EQ(42, x);
-}
-
-TEST_F(BindTest, EmptyFunctor) {
- struct NonEmptyFunctor {
- int operator()() const { return x; }
- int x = 42;
- };
-
- struct EmptyFunctor {
- int operator()() { return 42; }
- };
-
- struct EmptyFunctorConst {
- int operator()() const { return 42; }
- };
-
- EXPECT_TRUE(internal::IsCallableObject<NonEmptyFunctor>::value);
- EXPECT_TRUE(internal::IsCallableObject<EmptyFunctor>::value);
- EXPECT_TRUE(internal::IsCallableObject<EmptyFunctorConst>::value);
- EXPECT_EQ(42, BindOnce(EmptyFunctor()).Run());
- EXPECT_EQ(42, BindOnce(EmptyFunctorConst()).Run());
- EXPECT_EQ(42, BindRepeating(EmptyFunctorConst()).Run());
-}
-
-TEST_F(BindTest, CapturingLambdaForTesting) {
- int x = 6;
- EXPECT_EQ(42, BindLambdaForTesting([=](int y) { return x * y; }).Run(7));
-
- auto f = [x](std::unique_ptr<int> y) { return x * *y; };
- EXPECT_EQ(42, BindLambdaForTesting(f).Run(std::make_unique<int>(7)));
-}
-
-TEST_F(BindTest, Cancellation) {
- EXPECT_CALL(no_ref_, VoidMethodWithIntArg(_)).Times(2);
-
- WeakPtrFactory<NoRef> weak_factory(&no_ref_);
- RepeatingCallback<void(int)> cb =
- BindRepeating(&NoRef::VoidMethodWithIntArg, weak_factory.GetWeakPtr());
- RepeatingClosure cb2 = BindRepeating(cb, 8);
- OnceClosure cb3 = BindOnce(cb, 8);
-
- OnceCallback<void(int)> cb4 =
- BindOnce(&NoRef::VoidMethodWithIntArg, weak_factory.GetWeakPtr());
- EXPECT_FALSE(cb4.IsCancelled());
-
- OnceClosure cb5 = BindOnce(std::move(cb4), 8);
-
- EXPECT_FALSE(cb.IsCancelled());
- EXPECT_FALSE(cb2.IsCancelled());
- EXPECT_FALSE(cb3.IsCancelled());
- EXPECT_FALSE(cb5.IsCancelled());
-
- cb.Run(6);
- cb2.Run();
-
- weak_factory.InvalidateWeakPtrs();
-
- EXPECT_TRUE(cb.IsCancelled());
- EXPECT_TRUE(cb2.IsCancelled());
- EXPECT_TRUE(cb3.IsCancelled());
- EXPECT_TRUE(cb5.IsCancelled());
-
- cb.Run(6);
- cb2.Run();
- std::move(cb3).Run();
- std::move(cb5).Run();
-}
-
-TEST_F(BindTest, OnceCallback) {
- // Check if Callback variants have declarations of conversions as expected.
- // Copy constructor and assignment of RepeatingCallback.
- static_assert(std::is_constructible<
- RepeatingClosure, const RepeatingClosure&>::value,
- "RepeatingClosure should be copyable.");
- static_assert(
- std::is_assignable<RepeatingClosure, const RepeatingClosure&>::value,
- "RepeatingClosure should be copy-assignable.");
-
- // Move constructor and assignment of RepeatingCallback.
- static_assert(std::is_constructible<
- RepeatingClosure, RepeatingClosure&&>::value,
- "RepeatingClosure should be movable.");
- static_assert(std::is_assignable<RepeatingClosure, RepeatingClosure&&>::value,
- "RepeatingClosure should be move-assignable");
-
- // Conversions from OnceCallback to RepeatingCallback.
- static_assert(!std::is_constructible<
- RepeatingClosure, const OnceClosure&>::value,
- "OnceClosure should not be convertible to RepeatingClosure.");
- static_assert(
- !std::is_assignable<RepeatingClosure, const OnceClosure&>::value,
- "OnceClosure should not be convertible to RepeatingClosure.");
-
- // Destructive conversions from OnceCallback to RepeatingCallback.
- static_assert(!std::is_constructible<
- RepeatingClosure, OnceClosure&&>::value,
- "OnceClosure should not be convertible to RepeatingClosure.");
- static_assert(!std::is_assignable<RepeatingClosure, OnceClosure&&>::value,
- "OnceClosure should not be convertible to RepeatingClosure.");
-
- // Copy constructor and assignment of OnceCallback.
- static_assert(!std::is_constructible<
- OnceClosure, const OnceClosure&>::value,
- "OnceClosure should not be copyable.");
- static_assert(!std::is_assignable<OnceClosure, const OnceClosure&>::value,
- "OnceClosure should not be copy-assignable");
-
- // Move constructor and assignment of OnceCallback.
- static_assert(std::is_constructible<
- OnceClosure, OnceClosure&&>::value,
- "OnceClosure should be movable.");
- static_assert(std::is_assignable<OnceClosure, OnceClosure&&>::value,
- "OnceClosure should be move-assignable.");
-
- // Conversions from RepeatingCallback to OnceCallback.
- static_assert(std::is_constructible<
- OnceClosure, const RepeatingClosure&>::value,
- "RepeatingClosure should be convertible to OnceClosure.");
- static_assert(std::is_assignable<OnceClosure, const RepeatingClosure&>::value,
- "RepeatingClosure should be convertible to OnceClosure.");
-
- // Destructive conversions from RepeatingCallback to OnceCallback.
- static_assert(std::is_constructible<
- OnceClosure, RepeatingClosure&&>::value,
- "RepeatingClosure should be convertible to OnceClosure.");
- static_assert(std::is_assignable<OnceClosure, RepeatingClosure&&>::value,
- "RepeatingClosure should be covretible to OnceClosure.");
-
- OnceClosure cb = BindOnce(&VoidPolymorphic<>::Run);
- std::move(cb).Run();
-
- // RepeatingCallback should be convertible to OnceCallback.
- OnceClosure cb2 = BindRepeating(&VoidPolymorphic<>::Run);
- std::move(cb2).Run();
-
- RepeatingClosure cb3 = BindRepeating(&VoidPolymorphic<>::Run);
- cb = cb3;
- std::move(cb).Run();
-
- cb = std::move(cb2);
-
- OnceCallback<void(int)> cb4 =
- BindOnce(&VoidPolymorphic<std::unique_ptr<int>, int>::Run,
- std::make_unique<int>(0));
- BindOnce(std::move(cb4), 1).Run();
-}
-
-// Callback construction and assignment tests.
-// - Construction from an InvokerStorageHolder should not cause ref/deref.
-// - Assignment from other callback should only cause one ref
-//
-// TODO(ajwong): Is there actually a way to test this?
-
-#if defined(OS_WIN)
-int __fastcall FastCallFunc(int n) {
- return n;
-}
-
-int __stdcall StdCallFunc(int n) {
- return n;
-}
-
-// Windows specific calling convention support.
-// - Can bind a __fastcall function.
-// - Can bind a __stdcall function.
-TEST_F(BindTest, WindowsCallingConventions) {
- Callback<int()> fastcall_cb = Bind(&FastCallFunc, 1);
- EXPECT_EQ(1, fastcall_cb.Run());
-
- Callback<int()> stdcall_cb = Bind(&StdCallFunc, 2);
- EXPECT_EQ(2, stdcall_cb.Run());
-}
-#endif
-
-// Test unwrapping the various wrapping functions.
-
-TEST_F(BindTest, UnwrapUnretained) {
- int i = 0;
- auto unretained = Unretained(&i);
- EXPECT_EQ(&i, internal::Unwrap(unretained));
- EXPECT_EQ(&i, internal::Unwrap(std::move(unretained)));
-}
-
-TEST_F(BindTest, UnwrapConstRef) {
- int p = 0;
- auto const_ref = ConstRef(p);
- EXPECT_EQ(&p, &internal::Unwrap(const_ref));
- EXPECT_EQ(&p, &internal::Unwrap(std::move(const_ref)));
-}
-
-TEST_F(BindTest, UnwrapRetainedRef) {
- auto p = MakeRefCounted<RefCountedData<int>>();
- auto retained_ref = RetainedRef(p);
- EXPECT_EQ(p.get(), internal::Unwrap(retained_ref));
- EXPECT_EQ(p.get(), internal::Unwrap(std::move(retained_ref)));
-}
-
-TEST_F(BindTest, UnwrapOwned) {
- int* p = new int;
- auto owned = Owned(p);
- EXPECT_EQ(p, internal::Unwrap(owned));
- EXPECT_EQ(p, internal::Unwrap(std::move(owned)));
-}
-
-TEST_F(BindTest, UnwrapPassed) {
- int* p = new int;
- auto passed = Passed(WrapUnique(p));
- EXPECT_EQ(p, internal::Unwrap(passed).get());
-
- p = new int;
- EXPECT_EQ(p, internal::Unwrap(Passed(WrapUnique(p))).get());
-}
-
-TEST_F(BindTest, BindNoexcept) {
- EXPECT_EQ(42, base::BindOnce(&Noexcept).Run());
- EXPECT_EQ(
- 42,
- base::BindOnce(&BindTest::NoexceptMethod, base::Unretained(this)).Run());
- EXPECT_EQ(
- 42, base::BindOnce(&BindTest::ConstNoexceptMethod, base::Unretained(this))
- .Run());
-}
-
-// Test null callbacks cause a DCHECK.
-TEST(BindDeathTest, NullCallback) {
- base::Callback<void(int)> null_cb;
- ASSERT_TRUE(null_cb.is_null());
- EXPECT_DCHECK_DEATH(base::Bind(null_cb, 42));
-}
-
-} // namespace
-} // namespace base
diff --git a/base/bind_unittest.nc b/base/bind_unittest.nc
deleted file mode 100644
index d549d2e..0000000
--- 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 f36d3fe..0000000
--- 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/bits_unittest.cc b/base/bits_unittest.cc
deleted file mode 100644
index ceaad3f..0000000
--- a/base/bits_unittest.cc
+++ /dev/null
@@ -1,197 +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.
-
-// This file contains the unit tests for the bit utilities.
-
-#include "base/bits.h"
-#include "build_config.h"
-
-#include <stddef.h>
-
-#include <limits>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace bits {
-
-TEST(BitsTest, Log2Floor) {
- EXPECT_EQ(-1, Log2Floor(0));
- EXPECT_EQ(0, Log2Floor(1));
- EXPECT_EQ(1, Log2Floor(2));
- EXPECT_EQ(1, Log2Floor(3));
- EXPECT_EQ(2, Log2Floor(4));
- for (int i = 3; i < 31; ++i) {
- unsigned int value = 1U << i;
- EXPECT_EQ(i, Log2Floor(value));
- EXPECT_EQ(i, Log2Floor(value + 1));
- EXPECT_EQ(i, Log2Floor(value + 2));
- EXPECT_EQ(i - 1, Log2Floor(value - 1));
- EXPECT_EQ(i - 1, Log2Floor(value - 2));
- }
- EXPECT_EQ(31, Log2Floor(0xffffffffU));
-}
-
-TEST(BitsTest, Log2Ceiling) {
- EXPECT_EQ(-1, Log2Ceiling(0));
- EXPECT_EQ(0, Log2Ceiling(1));
- EXPECT_EQ(1, Log2Ceiling(2));
- EXPECT_EQ(2, Log2Ceiling(3));
- EXPECT_EQ(2, Log2Ceiling(4));
- for (int i = 3; i < 31; ++i) {
- unsigned int value = 1U << i;
- EXPECT_EQ(i, Log2Ceiling(value));
- EXPECT_EQ(i + 1, Log2Ceiling(value + 1));
- EXPECT_EQ(i + 1, Log2Ceiling(value + 2));
- EXPECT_EQ(i, Log2Ceiling(value - 1));
- EXPECT_EQ(i, Log2Ceiling(value - 2));
- }
- EXPECT_EQ(32, Log2Ceiling(0xffffffffU));
-}
-
-TEST(BitsTest, Align) {
- const size_t kSizeTMax = std::numeric_limits<size_t>::max();
- EXPECT_EQ(0ul, Align(0, 4));
- EXPECT_EQ(4ul, Align(1, 4));
- EXPECT_EQ(4096ul, Align(1, 4096));
- EXPECT_EQ(4096ul, Align(4096, 4096));
- EXPECT_EQ(4096ul, Align(4095, 4096));
- EXPECT_EQ(8192ul, Align(4097, 4096));
- EXPECT_EQ(kSizeTMax - 31, Align(kSizeTMax - 62, 32));
- EXPECT_EQ(kSizeTMax / 2 + 1, Align(1, kSizeTMax / 2 + 1));
-}
-
-TEST(BitsTest, CountLeadingZeroBits8) {
- EXPECT_EQ(8u, CountLeadingZeroBits(uint8_t{0}));
- EXPECT_EQ(7u, CountLeadingZeroBits(uint8_t{1}));
- for (uint8_t shift = 0; shift <= 7; shift++) {
- EXPECT_EQ(7u - shift,
- CountLeadingZeroBits(static_cast<uint8_t>(1 << shift)));
- }
- EXPECT_EQ(4u, CountLeadingZeroBits(uint8_t{0x0f}));
-}
-
-TEST(BitsTest, CountLeadingZeroBits16) {
- EXPECT_EQ(16u, CountLeadingZeroBits(uint16_t{0}));
- EXPECT_EQ(15u, CountLeadingZeroBits(uint16_t{1}));
- for (uint16_t shift = 0; shift <= 15; shift++) {
- EXPECT_EQ(15u - shift,
- CountLeadingZeroBits(static_cast<uint16_t>(1 << shift)));
- }
- EXPECT_EQ(4u, CountLeadingZeroBits(uint16_t{0x0f0f}));
-}
-
-TEST(BitsTest, CountLeadingZeroBits32) {
- EXPECT_EQ(32u, CountLeadingZeroBits(uint32_t{0}));
- EXPECT_EQ(31u, CountLeadingZeroBits(uint32_t{1}));
- for (uint32_t shift = 0; shift <= 31; shift++) {
- EXPECT_EQ(31u - shift, CountLeadingZeroBits(uint32_t{1} << shift));
- }
- EXPECT_EQ(4u, CountLeadingZeroBits(uint32_t{0x0f0f0f0f}));
-}
-
-TEST(BitsTest, CountTrailingeZeroBits8) {
- EXPECT_EQ(8u, CountTrailingZeroBits(uint8_t{0}));
- EXPECT_EQ(7u, CountTrailingZeroBits(uint8_t{128}));
- for (uint8_t shift = 0; shift <= 7; shift++) {
- EXPECT_EQ(shift, CountTrailingZeroBits(static_cast<uint8_t>(1 << shift)));
- }
- EXPECT_EQ(4u, CountTrailingZeroBits(uint8_t{0xf0}));
-}
-
-TEST(BitsTest, CountTrailingeZeroBits16) {
- EXPECT_EQ(16u, CountTrailingZeroBits(uint16_t{0}));
- EXPECT_EQ(15u, CountTrailingZeroBits(uint16_t{32768}));
- for (uint16_t shift = 0; shift <= 15; shift++) {
- EXPECT_EQ(shift, CountTrailingZeroBits(static_cast<uint16_t>(1 << shift)));
- }
- EXPECT_EQ(4u, CountTrailingZeroBits(uint16_t{0xf0f0}));
-}
-
-TEST(BitsTest, CountTrailingeZeroBits32) {
- EXPECT_EQ(32u, CountTrailingZeroBits(uint32_t{0}));
- EXPECT_EQ(31u, CountTrailingZeroBits(uint32_t{1} << 31));
- for (uint32_t shift = 0; shift <= 31; shift++) {
- EXPECT_EQ(shift, CountTrailingZeroBits(uint32_t{1} << shift));
- }
- EXPECT_EQ(4u, CountTrailingZeroBits(uint32_t{0xf0f0f0f0}));
-}
-
-#if defined(ARCH_CPU_64_BITS)
-
-TEST(BitsTest, CountLeadingZeroBits64) {
- EXPECT_EQ(64u, CountLeadingZeroBits(uint64_t{0}));
- EXPECT_EQ(63u, CountLeadingZeroBits(uint64_t{1}));
- for (uint64_t shift = 0; shift <= 63; shift++) {
- EXPECT_EQ(63u - shift, CountLeadingZeroBits(uint64_t{1} << shift));
- }
- EXPECT_EQ(4u, CountLeadingZeroBits(uint64_t{0x0f0f0f0f0f0f0f0f}));
-}
-
-TEST(BitsTest, CountTrailingeZeroBits64) {
- EXPECT_EQ(64u, CountTrailingZeroBits(uint64_t{0}));
- EXPECT_EQ(63u, CountTrailingZeroBits(uint64_t{1} << 63));
- for (uint64_t shift = 0; shift <= 31; shift++) {
- EXPECT_EQ(shift, CountTrailingZeroBits(uint64_t{1} << shift));
- }
- EXPECT_EQ(4u, CountTrailingZeroBits(uint64_t{0xf0f0f0f0f0f0f0f0}));
-}
-
-#endif // ARCH_CPU_64_BITS
-
-TEST(BitsTest, CountLeadingZeroBitsSizeT) {
-#if defined(ARCH_CPU_64_BITS)
- EXPECT_EQ(64u, CountLeadingZeroBitsSizeT(size_t{0}));
- EXPECT_EQ(63u, CountLeadingZeroBitsSizeT(size_t{1}));
- EXPECT_EQ(32u, CountLeadingZeroBitsSizeT(size_t{1} << 31));
- EXPECT_EQ(1u, CountLeadingZeroBitsSizeT(size_t{1} << 62));
- EXPECT_EQ(0u, CountLeadingZeroBitsSizeT(size_t{1} << 63));
-#else
- EXPECT_EQ(32u, CountLeadingZeroBitsSizeT(size_t{0}));
- EXPECT_EQ(31u, CountLeadingZeroBitsSizeT(size_t{1}));
- EXPECT_EQ(1u, CountLeadingZeroBitsSizeT(size_t{1} << 30));
- EXPECT_EQ(0u, CountLeadingZeroBitsSizeT(size_t{1} << 31));
-#endif // ARCH_CPU_64_BITS
-}
-
-TEST(BitsTest, CountTrailingZeroBitsSizeT) {
-#if defined(ARCH_CPU_64_BITS)
- EXPECT_EQ(64u, CountTrailingZeroBitsSizeT(size_t{0}));
- EXPECT_EQ(63u, CountTrailingZeroBitsSizeT(size_t{1} << 63));
- EXPECT_EQ(31u, CountTrailingZeroBitsSizeT(size_t{1} << 31));
- EXPECT_EQ(1u, CountTrailingZeroBitsSizeT(size_t{2}));
- EXPECT_EQ(0u, CountTrailingZeroBitsSizeT(size_t{1}));
-#else
- EXPECT_EQ(32u, CountTrailingZeroBitsSizeT(size_t{0}));
- EXPECT_EQ(31u, CountTrailingZeroBitsSizeT(size_t{1} << 31));
- EXPECT_EQ(1u, CountTrailingZeroBitsSizeT(size_t{2}));
- EXPECT_EQ(0u, CountTrailingZeroBitsSizeT(size_t{1}));
-#endif // ARCH_CPU_64_BITS
-}
-
-TEST(BitsTest, PowerOfTwo) {
- EXPECT_FALSE(IsPowerOfTwo(-1));
- EXPECT_FALSE(IsPowerOfTwo(0));
- EXPECT_TRUE(IsPowerOfTwo(1));
- EXPECT_TRUE(IsPowerOfTwo(2));
- // Unsigned 64 bit cases.
- for (uint32_t i = 2; i < 64; i++) {
- const uint64_t val = uint64_t{1} << i;
- EXPECT_FALSE(IsPowerOfTwo(val - 1));
- EXPECT_TRUE(IsPowerOfTwo(val));
- EXPECT_FALSE(IsPowerOfTwo(val + 1));
- }
- // Signed 64 bit cases.
- for (uint32_t i = 2; i < 63; i++) {
- const int64_t val = int64_t{1} << i;
- EXPECT_FALSE(IsPowerOfTwo(val - 1));
- EXPECT_TRUE(IsPowerOfTwo(val));
- EXPECT_FALSE(IsPowerOfTwo(val + 1));
- }
- // Signed integers with only the last bit set are negative, not powers of two.
- EXPECT_FALSE(IsPowerOfTwo(int64_t{1} << 63));
-}
-
-} // namespace bits
-} // namespace base
diff --git a/base/callback_helpers_unittest.cc b/base/callback_helpers_unittest.cc
deleted file mode 100644
index 1c1102d..0000000
--- a/base/callback_helpers_unittest.cc
+++ /dev/null
@@ -1,127 +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/callback_helpers.h"
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void Increment(int* value) {
- (*value)++;
-}
-
-TEST(CallbackHelpersTest, TestResetAndReturn) {
- int run_count = 0;
-
- base::Closure cb = base::Bind(&Increment, &run_count);
- EXPECT_EQ(0, run_count);
- base::ResetAndReturn(&cb).Run();
- EXPECT_EQ(1, run_count);
- EXPECT_FALSE(cb);
-
- run_count = 0;
-
- base::OnceClosure cb2 = base::BindOnce(&Increment, &run_count);
- EXPECT_EQ(0, run_count);
- base::ResetAndReturn(&cb2).Run();
- EXPECT_EQ(1, run_count);
- EXPECT_FALSE(cb2);
-}
-
-TEST(CallbackHelpersTest, TestScopedClosureRunnerExitScope) {
- int run_count = 0;
- {
- base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count));
- EXPECT_EQ(0, run_count);
- }
- EXPECT_EQ(1, run_count);
-}
-
-TEST(CallbackHelpersTest, TestScopedClosureRunnerRelease) {
- int run_count = 0;
- base::OnceClosure c;
- {
- base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count));
- c = runner.Release();
- EXPECT_EQ(0, run_count);
- }
- EXPECT_EQ(0, run_count);
- std::move(c).Run();
- EXPECT_EQ(1, run_count);
-}
-
-TEST(CallbackHelpersTest, TestScopedClosureRunnerReplaceClosure) {
- int run_count_1 = 0;
- int run_count_2 = 0;
- {
- base::ScopedClosureRunner runner;
- runner.ReplaceClosure(base::Bind(&Increment, &run_count_1));
- runner.ReplaceClosure(base::Bind(&Increment, &run_count_2));
- EXPECT_EQ(0, run_count_1);
- EXPECT_EQ(0, run_count_2);
- }
- EXPECT_EQ(0, run_count_1);
- EXPECT_EQ(1, run_count_2);
-}
-
-TEST(CallbackHelpersTest, TestScopedClosureRunnerRunAndReset) {
- int run_count_3 = 0;
- {
- base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count_3));
- EXPECT_EQ(0, run_count_3);
- runner.RunAndReset();
- EXPECT_EQ(1, run_count_3);
- }
- EXPECT_EQ(1, run_count_3);
-}
-
-TEST(CallbackHelpersTest, TestScopedClosureRunnerMoveConstructor) {
- int run_count = 0;
- {
- std::unique_ptr<base::ScopedClosureRunner> runner(
- new base::ScopedClosureRunner(base::Bind(&Increment, &run_count)));
- base::ScopedClosureRunner runner2(std::move(*runner));
- runner.reset();
- EXPECT_EQ(0, run_count);
- }
- EXPECT_EQ(1, run_count);
-}
-
-TEST(CallbackHelpersTest, TestScopedClosureRunnerMoveAssignment) {
- int run_count_1 = 0;
- int run_count_2 = 0;
- {
- base::ScopedClosureRunner runner(base::Bind(&Increment, &run_count_1));
- {
- base::ScopedClosureRunner runner2(base::Bind(&Increment, &run_count_2));
- runner = std::move(runner2);
- EXPECT_EQ(0, run_count_1);
- EXPECT_EQ(0, run_count_2);
- }
- EXPECT_EQ(0, run_count_1);
- EXPECT_EQ(0, run_count_2);
- }
- EXPECT_EQ(0, run_count_1);
- EXPECT_EQ(1, run_count_2);
-}
-
-TEST(CallbackHelpersTest, TestAdaptCallbackForRepeating) {
- int count = 0;
- base::OnceCallback<void(int*)> cb =
- base::BindOnce([](int* count) { ++*count; });
-
- base::RepeatingCallback<void(int*)> wrapped =
- base::AdaptCallbackForRepeating(std::move(cb));
-
- EXPECT_EQ(0, count);
- wrapped.Run(&count);
- EXPECT_EQ(1, count);
- wrapped.Run(&count);
- EXPECT_EQ(1, count);
-}
-
-} // namespace
diff --git a/base/callback_list_unittest.cc b/base/callback_list_unittest.cc
deleted file mode 100644
index 6eb5ff7..0000000
--- a/base/callback_list_unittest.cc
+++ /dev/null
@@ -1,339 +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/callback_list.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class Listener {
- public:
- Listener() : total_(0), scaler_(1) {}
- explicit Listener(int scaler) : total_(0), scaler_(scaler) {}
- void IncrementTotal() { total_++; }
- void IncrementByMultipleOfScaler(int x) { total_ += x * scaler_; }
-
- int total() const { return total_; }
-
- private:
- int total_;
- int scaler_;
- DISALLOW_COPY_AND_ASSIGN(Listener);
-};
-
-class Remover {
- public:
- Remover() : total_(0) {}
- void IncrementTotalAndRemove() {
- total_++;
- removal_subscription_.reset();
- }
- void SetSubscriptionToRemove(
- std::unique_ptr<CallbackList<void(void)>::Subscription> sub) {
- removal_subscription_ = std::move(sub);
- }
-
- int total() const { return total_; }
-
- private:
- int total_;
- std::unique_ptr<CallbackList<void(void)>::Subscription> removal_subscription_;
- DISALLOW_COPY_AND_ASSIGN(Remover);
-};
-
-class Adder {
- public:
- explicit Adder(CallbackList<void(void)>* cb_reg)
- : added_(false),
- total_(0),
- cb_reg_(cb_reg) {
- }
- void AddCallback() {
- if (!added_) {
- added_ = true;
- subscription_ =
- cb_reg_->Add(Bind(&Adder::IncrementTotal, Unretained(this)));
- }
- }
- void IncrementTotal() { total_++; }
-
- bool added() const { return added_; }
-
- int total() const { return total_; }
-
- private:
- bool added_;
- int total_;
- CallbackList<void(void)>* cb_reg_;
- std::unique_ptr<CallbackList<void(void)>::Subscription> subscription_;
- DISALLOW_COPY_AND_ASSIGN(Adder);
-};
-
-class Summer {
- public:
- Summer() : value_(0) {}
-
- void AddOneParam(int a) { value_ = a; }
- void AddTwoParam(int a, int b) { value_ = a + b; }
- void AddThreeParam(int a, int b, int c) { value_ = a + b + c; }
- void AddFourParam(int a, int b, int c, int d) { value_ = a + b + c + d; }
- void AddFiveParam(int a, int b, int c, int d, int e) {
- value_ = a + b + c + d + e;
- }
- void AddSixParam(int a, int b, int c, int d, int e , int f) {
- value_ = a + b + c + d + e + f;
- }
-
- int value() const { return value_; }
-
- private:
- int value_;
- DISALLOW_COPY_AND_ASSIGN(Summer);
-};
-
-class Counter {
- public:
- Counter() : value_(0) {}
-
- void Increment() { value_++; }
-
- int value() const { return value_; }
-
- private:
- int value_;
- DISALLOW_COPY_AND_ASSIGN(Counter);
-};
-
-// Sanity check that we can instantiate a CallbackList for each arity.
-TEST(CallbackListTest, ArityTest) {
- Summer s;
-
- CallbackList<void(int)> c1;
- std::unique_ptr<CallbackList<void(int)>::Subscription> subscription1 =
- c1.Add(Bind(&Summer::AddOneParam, Unretained(&s)));
-
- c1.Notify(1);
- EXPECT_EQ(1, s.value());
-
- CallbackList<void(int, int)> c2;
- std::unique_ptr<CallbackList<void(int, int)>::Subscription> subscription2 =
- c2.Add(Bind(&Summer::AddTwoParam, Unretained(&s)));
-
- c2.Notify(1, 2);
- EXPECT_EQ(3, s.value());
-
- CallbackList<void(int, int, int)> c3;
- std::unique_ptr<CallbackList<void(int, int, int)>::Subscription>
- subscription3 = c3.Add(Bind(&Summer::AddThreeParam, Unretained(&s)));
-
- c3.Notify(1, 2, 3);
- EXPECT_EQ(6, s.value());
-
- CallbackList<void(int, int, int, int)> c4;
- std::unique_ptr<CallbackList<void(int, int, int, int)>::Subscription>
- subscription4 = c4.Add(Bind(&Summer::AddFourParam, Unretained(&s)));
-
- c4.Notify(1, 2, 3, 4);
- EXPECT_EQ(10, s.value());
-
- CallbackList<void(int, int, int, int, int)> c5;
- std::unique_ptr<CallbackList<void(int, int, int, int, int)>::Subscription>
- subscription5 = c5.Add(Bind(&Summer::AddFiveParam, Unretained(&s)));
-
- c5.Notify(1, 2, 3, 4, 5);
- EXPECT_EQ(15, s.value());
-
- CallbackList<void(int, int, int, int, int, int)> c6;
- std::unique_ptr<
- CallbackList<void(int, int, int, int, int, int)>::Subscription>
- subscription6 = c6.Add(Bind(&Summer::AddSixParam, Unretained(&s)));
-
- c6.Notify(1, 2, 3, 4, 5, 6);
- EXPECT_EQ(21, s.value());
-}
-
-// Sanity check that closures added to the list will be run, and those removed
-// from the list will not be run.
-TEST(CallbackListTest, BasicTest) {
- CallbackList<void(void)> cb_reg;
- Listener a, b, c;
-
- std::unique_ptr<CallbackList<void(void)>::Subscription> a_subscription =
- cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&a)));
- std::unique_ptr<CallbackList<void(void)>::Subscription> b_subscription =
- cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b)));
-
- EXPECT_TRUE(a_subscription.get());
- EXPECT_TRUE(b_subscription.get());
-
- cb_reg.Notify();
-
- EXPECT_EQ(1, a.total());
- EXPECT_EQ(1, b.total());
-
- b_subscription.reset();
-
- std::unique_ptr<CallbackList<void(void)>::Subscription> c_subscription =
- cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&c)));
-
- cb_reg.Notify();
-
- EXPECT_EQ(2, a.total());
- EXPECT_EQ(1, b.total());
- EXPECT_EQ(1, c.total());
-
- a_subscription.reset();
- b_subscription.reset();
- c_subscription.reset();
-}
-
-// Sanity check that callbacks with details added to the list will be run, with
-// the correct details, and those removed from the list will not be run.
-TEST(CallbackListTest, BasicTestWithParams) {
- CallbackList<void(int)> cb_reg;
- Listener a(1), b(-1), c(1);
-
- std::unique_ptr<CallbackList<void(int)>::Subscription> a_subscription =
- cb_reg.Add(Bind(&Listener::IncrementByMultipleOfScaler, Unretained(&a)));
- std::unique_ptr<CallbackList<void(int)>::Subscription> b_subscription =
- cb_reg.Add(Bind(&Listener::IncrementByMultipleOfScaler, Unretained(&b)));
-
- EXPECT_TRUE(a_subscription.get());
- EXPECT_TRUE(b_subscription.get());
-
- cb_reg.Notify(10);
-
- EXPECT_EQ(10, a.total());
- EXPECT_EQ(-10, b.total());
-
- b_subscription.reset();
-
- std::unique_ptr<CallbackList<void(int)>::Subscription> c_subscription =
- cb_reg.Add(Bind(&Listener::IncrementByMultipleOfScaler, Unretained(&c)));
-
- cb_reg.Notify(10);
-
- EXPECT_EQ(20, a.total());
- EXPECT_EQ(-10, b.total());
- EXPECT_EQ(10, c.total());
-
- a_subscription.reset();
- b_subscription.reset();
- c_subscription.reset();
-}
-
-// Test the a callback can remove itself or a different callback from the list
-// during iteration without invalidating the iterator.
-TEST(CallbackListTest, RemoveCallbacksDuringIteration) {
- CallbackList<void(void)> cb_reg;
- Listener a, b;
- Remover remover_1, remover_2;
-
- std::unique_ptr<CallbackList<void(void)>::Subscription> remover_1_sub =
- cb_reg.Add(
- Bind(&Remover::IncrementTotalAndRemove, Unretained(&remover_1)));
- std::unique_ptr<CallbackList<void(void)>::Subscription> remover_2_sub =
- cb_reg.Add(
- Bind(&Remover::IncrementTotalAndRemove, Unretained(&remover_2)));
- std::unique_ptr<CallbackList<void(void)>::Subscription> a_subscription =
- cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&a)));
- std::unique_ptr<CallbackList<void(void)>::Subscription> b_subscription =
- cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b)));
-
- // |remover_1| will remove itself.
- remover_1.SetSubscriptionToRemove(std::move(remover_1_sub));
- // |remover_2| will remove a.
- remover_2.SetSubscriptionToRemove(std::move(a_subscription));
-
- cb_reg.Notify();
-
- // |remover_1| runs once (and removes itself), |remover_2| runs once (and
- // removes a), |a| never runs, and |b| runs once.
- EXPECT_EQ(1, remover_1.total());
- EXPECT_EQ(1, remover_2.total());
- EXPECT_EQ(0, a.total());
- EXPECT_EQ(1, b.total());
-
- cb_reg.Notify();
-
- // Only |remover_2| and |b| run this time.
- EXPECT_EQ(1, remover_1.total());
- EXPECT_EQ(2, remover_2.total());
- EXPECT_EQ(0, a.total());
- EXPECT_EQ(2, b.total());
-}
-
-// Test that a callback can add another callback to the list durning iteration
-// without invalidating the iterator. The newly added callback should be run on
-// the current iteration as will all other callbacks in the list.
-TEST(CallbackListTest, AddCallbacksDuringIteration) {
- CallbackList<void(void)> cb_reg;
- Adder a(&cb_reg);
- Listener b;
- std::unique_ptr<CallbackList<void(void)>::Subscription> a_subscription =
- cb_reg.Add(Bind(&Adder::AddCallback, Unretained(&a)));
- std::unique_ptr<CallbackList<void(void)>::Subscription> b_subscription =
- cb_reg.Add(Bind(&Listener::IncrementTotal, Unretained(&b)));
-
- cb_reg.Notify();
-
- EXPECT_EQ(1, a.total());
- EXPECT_EQ(1, b.total());
- EXPECT_TRUE(a.added());
-
- cb_reg.Notify();
-
- EXPECT_EQ(2, a.total());
- EXPECT_EQ(2, b.total());
-}
-
-// Sanity check: notifying an empty list is a no-op.
-TEST(CallbackListTest, EmptyList) {
- CallbackList<void(void)> cb_reg;
-
- cb_reg.Notify();
-}
-
-TEST(CallbackList, RemovalCallback) {
- Counter remove_count;
- CallbackList<void(void)> cb_reg;
- cb_reg.set_removal_callback(
- Bind(&Counter::Increment, Unretained(&remove_count)));
-
- std::unique_ptr<CallbackList<void(void)>::Subscription> subscription =
- cb_reg.Add(DoNothing());
-
- // Removing a subscription outside of iteration signals the callback.
- EXPECT_EQ(0, remove_count.value());
- subscription.reset();
- EXPECT_EQ(1, remove_count.value());
-
- // Configure two subscriptions to remove themselves.
- Remover remover_1, remover_2;
- std::unique_ptr<CallbackList<void(void)>::Subscription> remover_1_sub =
- cb_reg.Add(
- Bind(&Remover::IncrementTotalAndRemove, Unretained(&remover_1)));
- std::unique_ptr<CallbackList<void(void)>::Subscription> remover_2_sub =
- cb_reg.Add(
- Bind(&Remover::IncrementTotalAndRemove, Unretained(&remover_2)));
- remover_1.SetSubscriptionToRemove(std::move(remover_1_sub));
- remover_2.SetSubscriptionToRemove(std::move(remover_2_sub));
-
- // The callback should be signaled exactly once.
- EXPECT_EQ(1, remove_count.value());
- cb_reg.Notify();
- EXPECT_EQ(2, remove_count.value());
- EXPECT_TRUE(cb_reg.empty());
-}
-
-} // namespace
-} // namespace base
diff --git a/base/callback_list_unittest.nc b/base/callback_list_unittest.nc
deleted file mode 100644
index 7347f76..0000000
--- 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.cc b/base/callback_unittest.cc
deleted file mode 100644
index c07d3ee..0000000
--- a/base/callback_unittest.cc
+++ /dev/null
@@ -1,187 +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/callback.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/callback_helpers.h"
-#include "base/callback_internal.h"
-#include "base/memory/ref_counted.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-void NopInvokeFunc() {}
-
-// White-box testpoints to inject into a Callback<> object for checking
-// comparators and emptiness APIs. Use a BindState that is specialized
-// based on a type we declared in the anonymous namespace above to remove any
-// chance of colliding with another instantiation and breaking the
-// one-definition-rule.
-struct FakeBindState : internal::BindStateBase {
- FakeBindState() : BindStateBase(&NopInvokeFunc, &Destroy, &IsCancelled) {}
-
- private:
- ~FakeBindState() = default;
- static void Destroy(const internal::BindStateBase* self) {
- delete static_cast<const FakeBindState*>(self);
- }
- static bool IsCancelled(const internal::BindStateBase*) {
- return false;
- }
-};
-
-namespace {
-
-class CallbackTest : public ::testing::Test {
- public:
- CallbackTest()
- : callback_a_(new FakeBindState()), callback_b_(new FakeBindState()) {}
-
- ~CallbackTest() override = default;
-
- protected:
- Callback<void()> callback_a_;
- const Callback<void()> callback_b_; // Ensure APIs work with const.
- Callback<void()> null_callback_;
-};
-
-// Ensure we can create unbound callbacks. We need this to be able to store
-// them in class members that can be initialized later.
-TEST_F(CallbackTest, DefaultConstruction) {
- Callback<void()> c0;
- Callback<void(int)> c1;
- Callback<void(int,int)> c2;
- Callback<void(int,int,int)> c3;
- Callback<void(int,int,int,int)> c4;
- Callback<void(int,int,int,int,int)> c5;
- Callback<void(int,int,int,int,int,int)> c6;
-
- EXPECT_TRUE(c0.is_null());
- EXPECT_TRUE(c1.is_null());
- EXPECT_TRUE(c2.is_null());
- EXPECT_TRUE(c3.is_null());
- EXPECT_TRUE(c4.is_null());
- EXPECT_TRUE(c5.is_null());
- EXPECT_TRUE(c6.is_null());
-}
-
-TEST_F(CallbackTest, IsNull) {
- EXPECT_TRUE(null_callback_.is_null());
- EXPECT_FALSE(callback_a_.is_null());
- EXPECT_FALSE(callback_b_.is_null());
-}
-
-TEST_F(CallbackTest, Equals) {
- EXPECT_TRUE(callback_a_.Equals(callback_a_));
- EXPECT_FALSE(callback_a_.Equals(callback_b_));
- EXPECT_FALSE(callback_b_.Equals(callback_a_));
-
- // We should compare based on instance, not type.
- Callback<void()> callback_c(new FakeBindState());
- Callback<void()> callback_a2 = callback_a_;
- EXPECT_TRUE(callback_a_.Equals(callback_a2));
- EXPECT_FALSE(callback_a_.Equals(callback_c));
-
- // Empty, however, is always equal to empty.
- Callback<void()> empty2;
- EXPECT_TRUE(null_callback_.Equals(empty2));
-}
-
-TEST_F(CallbackTest, Reset) {
- // Resetting should bring us back to empty.
- ASSERT_FALSE(callback_a_.is_null());
- ASSERT_FALSE(callback_a_.Equals(null_callback_));
-
- callback_a_.Reset();
-
- EXPECT_TRUE(callback_a_.is_null());
- EXPECT_TRUE(callback_a_.Equals(null_callback_));
-}
-
-TEST_F(CallbackTest, Move) {
- // Moving should reset the callback.
- ASSERT_FALSE(callback_a_.is_null());
- ASSERT_FALSE(callback_a_.Equals(null_callback_));
-
- auto tmp = std::move(callback_a_);
-
- EXPECT_TRUE(callback_a_.is_null());
- EXPECT_TRUE(callback_a_.Equals(null_callback_));
-}
-
-struct TestForReentrancy {
- TestForReentrancy()
- : cb_already_run(false),
- cb(Bind(&TestForReentrancy::AssertCBIsNull, Unretained(this))) {
- }
- void AssertCBIsNull() {
- ASSERT_TRUE(cb.is_null());
- cb_already_run = true;
- }
- bool cb_already_run;
- Closure cb;
-};
-
-TEST_F(CallbackTest, ResetAndReturn) {
- TestForReentrancy tfr;
- ASSERT_FALSE(tfr.cb.is_null());
- ASSERT_FALSE(tfr.cb_already_run);
- ResetAndReturn(&tfr.cb).Run();
- ASSERT_TRUE(tfr.cb.is_null());
- ASSERT_TRUE(tfr.cb_already_run);
-}
-
-TEST_F(CallbackTest, NullAfterMoveRun) {
- Closure cb = Bind([] {});
- ASSERT_TRUE(cb);
- std::move(cb).Run();
- ASSERT_FALSE(cb);
-
- const Closure cb2 = Bind([] {});
- ASSERT_TRUE(cb2);
- std::move(cb2).Run();
- ASSERT_TRUE(cb2);
-
- OnceClosure cb3 = BindOnce([] {});
- ASSERT_TRUE(cb3);
- std::move(cb3).Run();
- ASSERT_FALSE(cb3);
-}
-
-class CallbackOwner : public base::RefCounted<CallbackOwner> {
- public:
- explicit CallbackOwner(bool* deleted) {
- callback_ = Bind(&CallbackOwner::Unused, this);
- deleted_ = deleted;
- }
- void Reset() {
- callback_.Reset();
- // We are deleted here if no-one else had a ref to us.
- }
-
- private:
- friend class base::RefCounted<CallbackOwner>;
- virtual ~CallbackOwner() {
- *deleted_ = true;
- }
- void Unused() {
- FAIL() << "Should never be called";
- }
-
- Closure callback_;
- bool* deleted_;
-};
-
-TEST_F(CallbackTest, CallbackHasLastRefOnContainingObject) {
- bool deleted = false;
- CallbackOwner* owner = new CallbackOwner(&deleted);
- owner->Reset();
- ASSERT_TRUE(deleted);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/callback_unittest.nc b/base/callback_unittest.nc
deleted file mode 100644
index 3261529..0000000
--- 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/cancelable_callback_unittest.cc b/base/cancelable_callback_unittest.cc
deleted file mode 100644
index 373498c..0000000
--- a/base/cancelable_callback_unittest.cc
+++ /dev/null
@@ -1,207 +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/cancelable_callback.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/memory/ptr_util.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_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class TestRefCounted : public RefCountedThreadSafe<TestRefCounted> {
- private:
- friend class RefCountedThreadSafe<TestRefCounted>;
- ~TestRefCounted() = default;
- ;
-};
-
-void Increment(int* count) { (*count)++; }
-void IncrementBy(int* count, int n) { (*count) += n; }
-void RefCountedParam(const scoped_refptr<TestRefCounted>& ref_counted) {}
-
-void OnMoveOnlyReceived(int* value, std::unique_ptr<int> result) {
- *value = *result;
-}
-
-// Cancel().
-// - Callback can be run multiple times.
-// - After Cancel(), Run() completes but has no effect.
-TEST(CancelableCallbackTest, Cancel) {
- int count = 0;
- CancelableClosure cancelable(
- base::Bind(&Increment, base::Unretained(&count)));
-
- base::Closure callback = cancelable.callback();
- callback.Run();
- EXPECT_EQ(1, count);
-
- callback.Run();
- EXPECT_EQ(2, count);
-
- cancelable.Cancel();
- callback.Run();
- EXPECT_EQ(2, count);
-}
-
-// Cancel() called multiple times.
-// - Cancel() cancels all copies of the wrapped callback.
-// - Calling Cancel() more than once has no effect.
-// - After Cancel(), callback() returns a null callback.
-TEST(CancelableCallbackTest, MultipleCancel) {
- int count = 0;
- CancelableClosure cancelable(
- base::Bind(&Increment, base::Unretained(&count)));
-
- base::Closure callback1 = cancelable.callback();
- base::Closure callback2 = cancelable.callback();
- cancelable.Cancel();
-
- callback1.Run();
- EXPECT_EQ(0, count);
-
- callback2.Run();
- EXPECT_EQ(0, count);
-
- // Calling Cancel() again has no effect.
- cancelable.Cancel();
-
- // callback() of a cancelled callback is null.
- base::Closure callback3 = cancelable.callback();
- EXPECT_TRUE(callback3.is_null());
-}
-
-// CancelableCallback destroyed before callback is run.
-// - Destruction of CancelableCallback cancels outstanding callbacks.
-TEST(CancelableCallbackTest, CallbackCanceledOnDestruction) {
- int count = 0;
- base::Closure callback;
-
- {
- CancelableClosure cancelable(
- base::Bind(&Increment, base::Unretained(&count)));
-
- callback = cancelable.callback();
- callback.Run();
- EXPECT_EQ(1, count);
- }
-
- callback.Run();
- EXPECT_EQ(1, count);
-}
-
-// Cancel() called on bound closure with a RefCounted parameter.
-// - Cancel drops wrapped callback (and, implicitly, its bound arguments).
-TEST(CancelableCallbackTest, CancelDropsCallback) {
- scoped_refptr<TestRefCounted> ref_counted = new TestRefCounted;
- EXPECT_TRUE(ref_counted->HasOneRef());
-
- CancelableClosure cancelable(base::Bind(RefCountedParam, ref_counted));
- EXPECT_FALSE(cancelable.IsCancelled());
- EXPECT_TRUE(ref_counted.get());
- EXPECT_FALSE(ref_counted->HasOneRef());
-
- // There is only one reference to |ref_counted| after the Cancel().
- cancelable.Cancel();
- EXPECT_TRUE(cancelable.IsCancelled());
- EXPECT_TRUE(ref_counted.get());
- EXPECT_TRUE(ref_counted->HasOneRef());
-}
-
-// Reset().
-// - Reset() replaces the existing wrapped callback with a new callback.
-// - Reset() deactivates outstanding callbacks.
-TEST(CancelableCallbackTest, Reset) {
- int count = 0;
- CancelableClosure cancelable(
- base::Bind(&Increment, base::Unretained(&count)));
-
- base::Closure callback = cancelable.callback();
- callback.Run();
- EXPECT_EQ(1, count);
-
- callback.Run();
- EXPECT_EQ(2, count);
-
- cancelable.Reset(
- base::Bind(&IncrementBy, base::Unretained(&count), 3));
- EXPECT_FALSE(cancelable.IsCancelled());
-
- // The stale copy of the cancelable callback is non-null.
- ASSERT_FALSE(callback.is_null());
-
- // The stale copy of the cancelable callback is no longer active.
- callback.Run();
- EXPECT_EQ(2, count);
-
- base::Closure callback2 = cancelable.callback();
- ASSERT_FALSE(callback2.is_null());
-
- callback2.Run();
- EXPECT_EQ(5, count);
-}
-
-// IsCanceled().
-// - Cancel() transforms the CancelableCallback into a cancelled state.
-TEST(CancelableCallbackTest, IsNull) {
- CancelableClosure cancelable;
- EXPECT_TRUE(cancelable.IsCancelled());
-
- int count = 0;
- cancelable.Reset(base::Bind(&Increment,
- base::Unretained(&count)));
- EXPECT_FALSE(cancelable.IsCancelled());
-
- cancelable.Cancel();
- EXPECT_TRUE(cancelable.IsCancelled());
-}
-
-// CancelableCallback posted to a MessageLoop with PostTask.
-// - Callbacks posted to a MessageLoop can be cancelled.
-TEST(CancelableCallbackTest, PostTask) {
- MessageLoop loop;
-
- int count = 0;
- CancelableClosure cancelable(base::Bind(&Increment,
- base::Unretained(&count)));
-
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, cancelable.callback());
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, count);
-
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, cancelable.callback());
-
- // Cancel before running the message loop.
- cancelable.Cancel();
- RunLoop().RunUntilIdle();
-
- // Callback never ran due to cancellation; count is the same.
- EXPECT_EQ(1, count);
-}
-
-// CancelableCallback can be used with move-only types.
-TEST(CancelableCallbackTest, MoveOnlyType) {
- const int kExpectedResult = 42;
-
- int result = 0;
- CancelableCallback<void(std::unique_ptr<int>)> cb(
- base::Bind(&OnMoveOnlyReceived, base::Unretained(&result)));
- cb.callback().Run(base::WrapUnique(new int(kExpectedResult)));
-
- EXPECT_EQ(kExpectedResult, result);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/command_line_unittest.cc b/base/command_line_unittest.cc
deleted file mode 100644
index 2396830..0000000
--- a/base/command_line_unittest.cc
+++ /dev/null
@@ -1,440 +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/command_line.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// To test Windows quoting behavior, we use a string that has some backslashes
-// and quotes.
-// Consider the command-line argument: q\"bs1\bs2\\bs3q\\\"
-// Here it is with C-style escapes.
-static const CommandLine::StringType kTrickyQuoted =
- FILE_PATH_LITERAL("q\\\"bs1\\bs2\\\\bs3q\\\\\\\"");
-// It should be parsed by Windows as: q"bs1\bs2\\bs3q\"
-// Here that is with C-style escapes.
-static const CommandLine::StringType kTricky =
- FILE_PATH_LITERAL("q\"bs1\\bs2\\\\bs3q\\\"");
-
-TEST(CommandLineTest, CommandLineConstructor) {
- const CommandLine::CharType* argv[] = {
- FILE_PATH_LITERAL("program"),
- FILE_PATH_LITERAL("--foo="),
- FILE_PATH_LITERAL("-bAr"),
- FILE_PATH_LITERAL("-spaetzel=pierogi"),
- FILE_PATH_LITERAL("-baz"),
- FILE_PATH_LITERAL("flim"),
- FILE_PATH_LITERAL("--other-switches=--dog=canine --cat=feline"),
- FILE_PATH_LITERAL("-spaetzle=Crepe"),
- FILE_PATH_LITERAL("-=loosevalue"),
- FILE_PATH_LITERAL("-"),
- FILE_PATH_LITERAL("FLAN"),
- FILE_PATH_LITERAL("a"),
- FILE_PATH_LITERAL("--input-translation=45--output-rotation"),
- FILE_PATH_LITERAL("--"),
- FILE_PATH_LITERAL("--"),
- FILE_PATH_LITERAL("--not-a-switch"),
- FILE_PATH_LITERAL("\"in the time of submarines...\""),
- FILE_PATH_LITERAL("unquoted arg-with-space")};
- CommandLine cl(arraysize(argv), argv);
-
- EXPECT_FALSE(cl.GetCommandLineString().empty());
- EXPECT_FALSE(cl.HasSwitch("cruller"));
- EXPECT_FALSE(cl.HasSwitch("flim"));
- EXPECT_FALSE(cl.HasSwitch("program"));
- EXPECT_FALSE(cl.HasSwitch("dog"));
- EXPECT_FALSE(cl.HasSwitch("cat"));
- EXPECT_FALSE(cl.HasSwitch("output-rotation"));
- EXPECT_FALSE(cl.HasSwitch("not-a-switch"));
- EXPECT_FALSE(cl.HasSwitch("--"));
-
- EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")).value(),
- cl.GetProgram().value());
-
- EXPECT_TRUE(cl.HasSwitch("foo"));
-#if defined(OS_WIN)
- EXPECT_TRUE(cl.HasSwitch("bar"));
-#else
- EXPECT_FALSE(cl.HasSwitch("bar"));
-#endif
- EXPECT_TRUE(cl.HasSwitch("baz"));
- EXPECT_TRUE(cl.HasSwitch("spaetzle"));
- EXPECT_TRUE(cl.HasSwitch("other-switches"));
- EXPECT_TRUE(cl.HasSwitch("input-translation"));
-
- EXPECT_EQ("Crepe", cl.GetSwitchValueASCII("spaetzle"));
- EXPECT_EQ("", cl.GetSwitchValueASCII("foo"));
- EXPECT_EQ("", cl.GetSwitchValueASCII("bar"));
- EXPECT_EQ("", cl.GetSwitchValueASCII("cruller"));
- EXPECT_EQ("--dog=canine --cat=feline", cl.GetSwitchValueASCII(
- "other-switches"));
- EXPECT_EQ("45--output-rotation", cl.GetSwitchValueASCII("input-translation"));
-
- const CommandLine::StringVector& args = cl.GetArgs();
- ASSERT_EQ(8U, args.size());
-
- std::vector<CommandLine::StringType>::const_iterator iter = args.begin();
- EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("-"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("FLAN"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("a"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("--"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("--not-a-switch"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("\"in the time of submarines...\""), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("unquoted arg-with-space"), *iter);
- ++iter;
- EXPECT_TRUE(iter == args.end());
-}
-
-TEST(CommandLineTest, CommandLineFromString) {
-#if defined(OS_WIN)
- CommandLine cl = CommandLine::FromString(
- L"program --foo= -bAr /Spaetzel=pierogi /Baz flim "
- L"--other-switches=\"--dog=canine --cat=feline\" "
- L"-spaetzle=Crepe -=loosevalue FLAN "
- L"--input-translation=\"45\"--output-rotation "
- L"--quotes=" + kTrickyQuoted + L" "
- L"-- -- --not-a-switch "
- L"\"in the time of submarines...\"");
-
- EXPECT_FALSE(cl.GetCommandLineString().empty());
- EXPECT_FALSE(cl.HasSwitch("cruller"));
- EXPECT_FALSE(cl.HasSwitch("flim"));
- EXPECT_FALSE(cl.HasSwitch("program"));
- EXPECT_FALSE(cl.HasSwitch("dog"));
- EXPECT_FALSE(cl.HasSwitch("cat"));
- EXPECT_FALSE(cl.HasSwitch("output-rotation"));
- EXPECT_FALSE(cl.HasSwitch("not-a-switch"));
- EXPECT_FALSE(cl.HasSwitch("--"));
-
- EXPECT_EQ(FilePath(FILE_PATH_LITERAL("program")).value(),
- cl.GetProgram().value());
-
- EXPECT_TRUE(cl.HasSwitch("foo"));
- EXPECT_TRUE(cl.HasSwitch("bar"));
- EXPECT_TRUE(cl.HasSwitch("baz"));
- EXPECT_TRUE(cl.HasSwitch("spaetzle"));
- EXPECT_TRUE(cl.HasSwitch("other-switches"));
- EXPECT_TRUE(cl.HasSwitch("input-translation"));
- EXPECT_TRUE(cl.HasSwitch("quotes"));
-
- EXPECT_EQ("Crepe", cl.GetSwitchValueASCII("spaetzle"));
- EXPECT_EQ("", cl.GetSwitchValueASCII("foo"));
- EXPECT_EQ("", cl.GetSwitchValueASCII("bar"));
- EXPECT_EQ("", cl.GetSwitchValueASCII("cruller"));
- EXPECT_EQ("--dog=canine --cat=feline", cl.GetSwitchValueASCII(
- "other-switches"));
- EXPECT_EQ("45--output-rotation", cl.GetSwitchValueASCII("input-translation"));
- EXPECT_EQ(kTricky, cl.GetSwitchValueNative("quotes"));
-
- const CommandLine::StringVector& args = cl.GetArgs();
- ASSERT_EQ(5U, args.size());
-
- std::vector<CommandLine::StringType>::const_iterator iter = args.begin();
- EXPECT_EQ(FILE_PATH_LITERAL("flim"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("FLAN"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("--"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("--not-a-switch"), *iter);
- ++iter;
- EXPECT_EQ(FILE_PATH_LITERAL("in the time of submarines..."), *iter);
- ++iter;
- EXPECT_TRUE(iter == args.end());
-
- // Check that a generated string produces an equivalent command line.
- CommandLine cl_duplicate = CommandLine::FromString(cl.GetCommandLineString());
- EXPECT_EQ(cl.GetCommandLineString(), cl_duplicate.GetCommandLineString());
-#endif
-}
-
-// Tests behavior with an empty input string.
-TEST(CommandLineTest, EmptyString) {
-#if defined(OS_WIN)
- CommandLine cl_from_string = CommandLine::FromString(L"");
- EXPECT_TRUE(cl_from_string.GetCommandLineString().empty());
- EXPECT_TRUE(cl_from_string.GetProgram().empty());
- EXPECT_EQ(1U, cl_from_string.argv().size());
- EXPECT_TRUE(cl_from_string.GetArgs().empty());
-#endif
- CommandLine cl_from_argv(0, nullptr);
- EXPECT_TRUE(cl_from_argv.GetCommandLineString().empty());
- EXPECT_TRUE(cl_from_argv.GetProgram().empty());
- EXPECT_EQ(1U, cl_from_argv.argv().size());
- EXPECT_TRUE(cl_from_argv.GetArgs().empty());
-}
-
-TEST(CommandLineTest, GetArgumentsString) {
- static const FilePath::CharType kPath1[] =
- FILE_PATH_LITERAL("C:\\Some File\\With Spaces.ggg");
- static const FilePath::CharType kPath2[] =
- FILE_PATH_LITERAL("C:\\no\\spaces.ggg");
-
- static const char kFirstArgName[] = "first-arg";
- static const char kSecondArgName[] = "arg2";
- static const char kThirdArgName[] = "arg with space";
- static const char kFourthArgName[] = "nospace";
- static const char kFifthArgName[] = "%1";
-
- CommandLine cl(CommandLine::NO_PROGRAM);
- cl.AppendSwitchPath(kFirstArgName, FilePath(kPath1));
- cl.AppendSwitchPath(kSecondArgName, FilePath(kPath2));
- cl.AppendArg(kThirdArgName);
- cl.AppendArg(kFourthArgName);
- cl.AppendArg(kFifthArgName);
-
-#if defined(OS_WIN)
- CommandLine::StringType expected_first_arg(UTF8ToUTF16(kFirstArgName));
- CommandLine::StringType expected_second_arg(UTF8ToUTF16(kSecondArgName));
- CommandLine::StringType expected_third_arg(UTF8ToUTF16(kThirdArgName));
- CommandLine::StringType expected_fourth_arg(UTF8ToUTF16(kFourthArgName));
- CommandLine::StringType expected_fifth_arg(UTF8ToUTF16(kFifthArgName));
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- CommandLine::StringType expected_first_arg(kFirstArgName);
- CommandLine::StringType expected_second_arg(kSecondArgName);
- CommandLine::StringType expected_third_arg(kThirdArgName);
- CommandLine::StringType expected_fourth_arg(kFourthArgName);
- CommandLine::StringType expected_fifth_arg(kFifthArgName);
-#endif
-
-#if defined(OS_WIN)
-#define QUOTE_ON_WIN FILE_PATH_LITERAL("\"")
-#else
-#define QUOTE_ON_WIN FILE_PATH_LITERAL("")
-#endif // OS_WIN
-
- CommandLine::StringType expected_str;
- expected_str.append(FILE_PATH_LITERAL("--"))
- .append(expected_first_arg)
- .append(FILE_PATH_LITERAL("="))
- .append(QUOTE_ON_WIN)
- .append(kPath1)
- .append(QUOTE_ON_WIN)
- .append(FILE_PATH_LITERAL(" "))
- .append(FILE_PATH_LITERAL("--"))
- .append(expected_second_arg)
- .append(FILE_PATH_LITERAL("="))
- .append(QUOTE_ON_WIN)
- .append(kPath2)
- .append(QUOTE_ON_WIN)
- .append(FILE_PATH_LITERAL(" "))
- .append(QUOTE_ON_WIN)
- .append(expected_third_arg)
- .append(QUOTE_ON_WIN)
- .append(FILE_PATH_LITERAL(" "))
- .append(expected_fourth_arg)
- .append(FILE_PATH_LITERAL(" "));
-
- CommandLine::StringType expected_str_no_quote_placeholders(expected_str);
- expected_str_no_quote_placeholders.append(expected_fifth_arg);
- EXPECT_EQ(expected_str_no_quote_placeholders, cl.GetArgumentsString());
-
-#if defined(OS_WIN)
- CommandLine::StringType expected_str_quote_placeholders(expected_str);
- expected_str_quote_placeholders.append(QUOTE_ON_WIN)
- .append(expected_fifth_arg)
- .append(QUOTE_ON_WIN);
- EXPECT_EQ(expected_str_quote_placeholders,
- cl.GetArgumentsStringWithPlaceholders());
-#endif
-}
-
-// Test methods for appending switches to a command line.
-TEST(CommandLineTest, AppendSwitches) {
- std::string switch1 = "switch1";
- std::string switch2 = "switch2";
- std::string value2 = "value";
- std::string switch3 = "switch3";
- std::string value3 = "a value with spaces";
- std::string switch4 = "switch4";
- std::string value4 = "\"a value with quotes\"";
- std::string switch5 = "quotes";
- CommandLine::StringType value5 = kTricky;
-
- CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
-
- cl.AppendSwitch(switch1);
- cl.AppendSwitchASCII(switch2, value2);
- cl.AppendSwitchASCII(switch3, value3);
- cl.AppendSwitchASCII(switch4, value4);
- cl.AppendSwitchASCII(switch5, value4);
- cl.AppendSwitchNative(switch5, value5);
-
- EXPECT_TRUE(cl.HasSwitch(switch1));
- EXPECT_TRUE(cl.HasSwitch(switch2));
- EXPECT_EQ(value2, cl.GetSwitchValueASCII(switch2));
- EXPECT_TRUE(cl.HasSwitch(switch3));
- EXPECT_EQ(value3, cl.GetSwitchValueASCII(switch3));
- EXPECT_TRUE(cl.HasSwitch(switch4));
- EXPECT_EQ(value4, cl.GetSwitchValueASCII(switch4));
- EXPECT_TRUE(cl.HasSwitch(switch5));
- EXPECT_EQ(value5, cl.GetSwitchValueNative(switch5));
-
-#if defined(OS_WIN)
- EXPECT_EQ(L"Program "
- L"--switch1 "
- L"--switch2=value "
- L"--switch3=\"a value with spaces\" "
- L"--switch4=\"\\\"a value with quotes\\\"\" "
- // Even though the switches are unique, appending can add repeat
- // switches to argv.
- L"--quotes=\"\\\"a value with quotes\\\"\" "
- L"--quotes=\"" + kTrickyQuoted + L"\"",
- cl.GetCommandLineString());
-#endif
-}
-
-TEST(CommandLineTest, AppendSwitchesDashDash) {
- const CommandLine::CharType* raw_argv[] = { FILE_PATH_LITERAL("prog"),
- FILE_PATH_LITERAL("--"),
- FILE_PATH_LITERAL("--arg1") };
- CommandLine cl(arraysize(raw_argv), raw_argv);
-
- cl.AppendSwitch("switch1");
- cl.AppendSwitchASCII("switch2", "foo");
-
- cl.AppendArg("--arg2");
-
- EXPECT_EQ(FILE_PATH_LITERAL("prog --switch1 --switch2=foo -- --arg1 --arg2"),
- cl.GetCommandLineString());
- CommandLine::StringVector cl_argv = cl.argv();
- EXPECT_EQ(FILE_PATH_LITERAL("prog"), cl_argv[0]);
- EXPECT_EQ(FILE_PATH_LITERAL("--switch1"), cl_argv[1]);
- EXPECT_EQ(FILE_PATH_LITERAL("--switch2=foo"), cl_argv[2]);
- EXPECT_EQ(FILE_PATH_LITERAL("--"), cl_argv[3]);
- EXPECT_EQ(FILE_PATH_LITERAL("--arg1"), cl_argv[4]);
- EXPECT_EQ(FILE_PATH_LITERAL("--arg2"), cl_argv[5]);
-}
-
-// Tests that when AppendArguments is called that the program is set correctly
-// on the target CommandLine object and the switches from the source
-// CommandLine are added to the target.
-TEST(CommandLineTest, AppendArguments) {
- CommandLine cl1(FilePath(FILE_PATH_LITERAL("Program")));
- cl1.AppendSwitch("switch1");
- cl1.AppendSwitchASCII("switch2", "foo");
-
- CommandLine cl2(CommandLine::NO_PROGRAM);
- cl2.AppendArguments(cl1, true);
- EXPECT_EQ(cl1.GetProgram().value(), cl2.GetProgram().value());
- EXPECT_EQ(cl1.GetCommandLineString(), cl2.GetCommandLineString());
-
- CommandLine c1(FilePath(FILE_PATH_LITERAL("Program1")));
- c1.AppendSwitch("switch1");
- CommandLine c2(FilePath(FILE_PATH_LITERAL("Program2")));
- c2.AppendSwitch("switch2");
-
- c1.AppendArguments(c2, true);
- EXPECT_EQ(c1.GetProgram().value(), c2.GetProgram().value());
- EXPECT_TRUE(c1.HasSwitch("switch1"));
- EXPECT_TRUE(c1.HasSwitch("switch2"));
-}
-
-#if defined(OS_WIN)
-// Make sure that the command line string program paths are quoted as necessary.
-// This only makes sense on Windows and the test is basically here to guard
-// against regressions.
-TEST(CommandLineTest, ProgramQuotes) {
- // Check that quotes are not added for paths without spaces.
- const FilePath kProgram(L"Program");
- CommandLine cl_program(kProgram);
- EXPECT_EQ(kProgram.value(), cl_program.GetProgram().value());
- EXPECT_EQ(kProgram.value(), cl_program.GetCommandLineString());
-
- const FilePath kProgramPath(L"Program Path");
-
- // Check that quotes are not returned from GetProgram().
- CommandLine cl_program_path(kProgramPath);
- EXPECT_EQ(kProgramPath.value(), cl_program_path.GetProgram().value());
-
- // Check that quotes are added to command line string paths containing spaces.
- CommandLine::StringType cmd_string(cl_program_path.GetCommandLineString());
- EXPECT_EQ(L"\"Program Path\"", cmd_string);
-
- // Check the optional quoting of placeholders in programs.
- CommandLine cl_quote_placeholder(FilePath(L"%1"));
- EXPECT_EQ(L"%1", cl_quote_placeholder.GetCommandLineString());
- EXPECT_EQ(L"\"%1\"",
- cl_quote_placeholder.GetCommandLineStringWithPlaceholders());
-}
-#endif
-
-// Calling Init multiple times should not modify the previous CommandLine.
-TEST(CommandLineTest, Init) {
- // Call Init without checking output once so we know it's been called
- // whether or not the test runner does so.
- CommandLine::Init(0, nullptr);
- CommandLine* initial = CommandLine::ForCurrentProcess();
- EXPECT_FALSE(CommandLine::Init(0, nullptr));
- CommandLine* current = CommandLine::ForCurrentProcess();
- EXPECT_EQ(initial, current);
-}
-
-// Test that copies of CommandLine have a valid StringPiece map.
-TEST(CommandLineTest, Copy) {
- std::unique_ptr<CommandLine> initial(
- new CommandLine(CommandLine::NO_PROGRAM));
- initial->AppendSwitch("a");
- initial->AppendSwitch("bbbbbbbbbbbbbbb");
- initial->AppendSwitch("c");
- CommandLine copy_constructed(*initial);
- CommandLine assigned = *initial;
- CommandLine::SwitchMap switch_map = initial->GetSwitches();
- initial.reset();
- for (const auto& pair : switch_map)
- EXPECT_TRUE(copy_constructed.HasSwitch(pair.first));
- for (const auto& pair : switch_map)
- EXPECT_TRUE(assigned.HasSwitch(pair.first));
-}
-
-TEST(CommandLineTest, PrependSimpleWrapper) {
- CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
- cl.AppendSwitch("a");
- cl.AppendSwitch("b");
- cl.PrependWrapper(FILE_PATH_LITERAL("wrapper --foo --bar"));
-
- EXPECT_EQ(6u, cl.argv().size());
- EXPECT_EQ(FILE_PATH_LITERAL("wrapper"), cl.argv()[0]);
- EXPECT_EQ(FILE_PATH_LITERAL("--foo"), cl.argv()[1]);
- EXPECT_EQ(FILE_PATH_LITERAL("--bar"), cl.argv()[2]);
- EXPECT_EQ(FILE_PATH_LITERAL("Program"), cl.argv()[3]);
- EXPECT_EQ(FILE_PATH_LITERAL("--a"), cl.argv()[4]);
- EXPECT_EQ(FILE_PATH_LITERAL("--b"), cl.argv()[5]);
-}
-
-TEST(CommandLineTest, PrependComplexWrapper) {
- CommandLine cl(FilePath(FILE_PATH_LITERAL("Program")));
- cl.AppendSwitch("a");
- cl.AppendSwitch("b");
- cl.PrependWrapper(
- FILE_PATH_LITERAL("wrapper --foo='hello world' --bar=\"let's go\""));
-
- EXPECT_EQ(6u, cl.argv().size());
- EXPECT_EQ(FILE_PATH_LITERAL("wrapper"), cl.argv()[0]);
- EXPECT_EQ(FILE_PATH_LITERAL("--foo='hello world'"), cl.argv()[1]);
- EXPECT_EQ(FILE_PATH_LITERAL("--bar=\"let's go\""), cl.argv()[2]);
- EXPECT_EQ(FILE_PATH_LITERAL("Program"), cl.argv()[3]);
- EXPECT_EQ(FILE_PATH_LITERAL("--a"), cl.argv()[4]);
- EXPECT_EQ(FILE_PATH_LITERAL("--b"), cl.argv()[5]);
-}
-
-} // namespace base
diff --git a/base/component_export_unittest.cc b/base/component_export_unittest.cc
deleted file mode 100644
index e994353..0000000
--- a/base/component_export_unittest.cc
+++ /dev/null
@@ -1,82 +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/component_export.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-using ComponentExportTest = testing::Test;
-
-#define IS_TEST_COMPONENT_A_IMPL 1
-#define IS_TEST_COMPONENT_B_IMPL
-#define IS_TEST_COMPONENT_C_IMPL 0
-#define IS_TEST_COMPONENT_D_IMPL 2
-#define IS_TEST_COMPONENT_E_IMPL xyz
-
-TEST(ComponentExportTest, ImportExport) {
- // Defined as 1. Treat as export.
- EXPECT_EQ(1, INSIDE_COMPONENT_IMPL(TEST_COMPONENT_A));
-
- // Defined, but empty. Treat as import.
- EXPECT_EQ(0, INSIDE_COMPONENT_IMPL(TEST_COMPONENT_B));
-
- // Defined, but 0. Treat as import.
- EXPECT_EQ(0, INSIDE_COMPONENT_IMPL(TEST_COMPONENT_C));
-
- // Defined, but some other arbitrary thing that isn't 1. Treat as import.
- EXPECT_EQ(0, INSIDE_COMPONENT_IMPL(TEST_COMPONENT_D));
- EXPECT_EQ(0, INSIDE_COMPONENT_IMPL(TEST_COMPONENT_E));
-
- // Undefined. Treat as import.
- EXPECT_EQ(0, INSIDE_COMPONENT_IMPL(TEST_COMPONENT_F));
-
- // And just for good measure, ensure that the macros evaluate properly in the
- // context of preprocessor #if blocks.
-#if INSIDE_COMPONENT_IMPL(TEST_COMPONENT_A)
- EXPECT_TRUE(true);
-#else
- EXPECT_TRUE(false);
-#endif
-
-#if !INSIDE_COMPONENT_IMPL(TEST_COMPONENT_B)
- EXPECT_TRUE(true);
-#else
- EXPECT_TRUE(false);
-#endif
-
-#if !INSIDE_COMPONENT_IMPL(TEST_COMPONENT_C)
- EXPECT_TRUE(true);
-#else
- EXPECT_TRUE(false);
-#endif
-
-#if !INSIDE_COMPONENT_IMPL(TEST_COMPONENT_D)
- EXPECT_TRUE(true);
-#else
- EXPECT_TRUE(false);
-#endif
-
-#if !INSIDE_COMPONENT_IMPL(TEST_COMPONENT_E)
- EXPECT_TRUE(true);
-#else
- EXPECT_TRUE(false);
-#endif
-
-#if !INSIDE_COMPONENT_IMPL(TEST_COMPONENT_F)
- EXPECT_TRUE(true);
-#else
- EXPECT_TRUE(false);
-#endif
-}
-
-#undef IS_TEST_COMPONENT_A_IMPL
-#undef IS_TEST_COMPONENT_B_IMPL
-#undef IS_TEST_COMPONENT_C_IMPL
-#undef IS_TEST_COMPONENT_D_IMPL
-#undef IS_TEST_COMPONENT_E_IMPL
-
-} // namespace
-} // namespace base
diff --git a/base/containers/adapters_unittest.cc b/base/containers/adapters_unittest.cc
deleted file mode 100644
index 92554b7..0000000
--- 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/circular_deque_unittest.cc b/base/containers/circular_deque_unittest.cc
deleted file mode 100644
index 0c168e0..0000000
--- a/base/containers/circular_deque_unittest.cc
+++ /dev/null
@@ -1,881 +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/circular_deque.h"
-
-#include "base/test/copy_only_int.h"
-#include "base/test/move_only_int.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::internal::VectorBuffer;
-
-namespace base {
-
-namespace {
-
-circular_deque<int> MakeSequence(size_t max) {
- circular_deque<int> ret;
- for (size_t i = 0; i < max; i++)
- ret.push_back(i);
- return ret;
-}
-
-// Cycles through the queue, popping items from the back and pushing items
-// at the front to validate behavior across different configurations of the
-// queue in relation to the underlying buffer. The tester closure is run for
-// each cycle.
-template <class QueueT, class Tester>
-void CycleTest(circular_deque<QueueT>& queue, const Tester& tester) {
- size_t steps = queue.size() * 2;
- for (size_t i = 0; i < steps; i++) {
- tester(queue, i);
- queue.pop_back();
- queue.push_front(QueueT());
- }
-}
-
-class DestructorCounter {
- public:
- DestructorCounter(int* counter) : counter_(counter) {}
- ~DestructorCounter() { ++(*counter_); }
-
- private:
- int* counter_;
-};
-
-} // namespace
-
-TEST(CircularDeque, FillConstructor) {
- constexpr size_t num_elts = 9;
-
- std::vector<int> foo(15);
- EXPECT_EQ(15u, foo.size());
-
- // Fill with default constructor.
- {
- circular_deque<int> buf(num_elts);
-
- EXPECT_EQ(num_elts, buf.size());
- EXPECT_EQ(num_elts, static_cast<size_t>(buf.end() - buf.begin()));
-
- for (size_t i = 0; i < num_elts; i++)
- EXPECT_EQ(0, buf[i]);
- }
-
- // Fill with explicit value.
- {
- int value = 199;
- circular_deque<int> buf(num_elts, value);
-
- EXPECT_EQ(num_elts, buf.size());
- EXPECT_EQ(num_elts, static_cast<size_t>(buf.end() - buf.begin()));
-
- for (size_t i = 0; i < num_elts; i++)
- EXPECT_EQ(value, buf[i]);
- }
-}
-
-TEST(CircularDeque, CopyAndRangeConstructor) {
- int values[] = {1, 2, 3, 4, 5, 6};
- circular_deque<CopyOnlyInt> first(std::begin(values), std::end(values));
-
- circular_deque<CopyOnlyInt> second(first);
- EXPECT_EQ(6u, second.size());
- for (int i = 0; i < 6; i++)
- EXPECT_EQ(i + 1, second[i].data());
-}
-
-TEST(CircularDeque, MoveConstructor) {
- int values[] = {1, 2, 3, 4, 5, 6};
- circular_deque<MoveOnlyInt> first(std::begin(values), std::end(values));
-
- circular_deque<MoveOnlyInt> second(std::move(first));
- EXPECT_TRUE(first.empty());
- EXPECT_EQ(6u, second.size());
- for (int i = 0; i < 6; i++)
- EXPECT_EQ(i + 1, second[i].data());
-}
-
-TEST(CircularDeque, InitializerListConstructor) {
- circular_deque<int> empty({});
- ASSERT_TRUE(empty.empty());
-
- circular_deque<int> first({1, 2, 3, 4, 5, 6});
- EXPECT_EQ(6u, first.size());
- for (int i = 0; i < 6; i++)
- EXPECT_EQ(i + 1, first[i]);
-}
-
-TEST(CircularDeque, Destructor) {
- int destruct_count = 0;
-
- // Contiguous buffer.
- {
- circular_deque<DestructorCounter> q;
- q.resize(5, DestructorCounter(&destruct_count));
-
- EXPECT_EQ(1, destruct_count); // The temporary in the call to resize().
- destruct_count = 0;
- }
- EXPECT_EQ(5, destruct_count); // One call for each.
-
- // Force a wraparound buffer.
- {
- circular_deque<DestructorCounter> q;
- q.reserve(7);
- q.resize(5, DestructorCounter(&destruct_count));
-
- // Cycle throught some elements in our buffer to force a wraparound.
- destruct_count = 0;
- for (int i = 0; i < 4; i++) {
- q.emplace_back(&destruct_count);
- q.pop_front();
- }
- EXPECT_EQ(4, destruct_count); // One for each cycle.
- destruct_count = 0;
- }
- EXPECT_EQ(5, destruct_count); // One call for each.
-}
-
-TEST(CircularDeque, EqualsCopy) {
- circular_deque<int> first = {1, 2, 3, 4, 5, 6};
- circular_deque<int> copy;
- EXPECT_TRUE(copy.empty());
- copy = first;
- EXPECT_EQ(6u, copy.size());
- for (int i = 0; i < 6; i++) {
- EXPECT_EQ(i + 1, first[i]);
- EXPECT_EQ(i + 1, copy[i]);
- EXPECT_NE(&first[i], ©[i]);
- }
-}
-
-TEST(CircularDeque, EqualsMove) {
- circular_deque<int> first = {1, 2, 3, 4, 5, 6};
- circular_deque<int> move;
- EXPECT_TRUE(move.empty());
- move = std::move(first);
- EXPECT_TRUE(first.empty());
- EXPECT_EQ(6u, move.size());
- for (int i = 0; i < 6; i++)
- EXPECT_EQ(i + 1, move[i]);
-}
-
-// Tests that self-assignment is a no-op.
-TEST(CircularDeque, EqualsSelf) {
- circular_deque<int> q = {1, 2, 3, 4, 5, 6};
- q = *&q; // The *& defeats Clang's -Wself-assign warning.
- EXPECT_EQ(6u, q.size());
- for (int i = 0; i < 6; i++)
- EXPECT_EQ(i + 1, q[i]);
-}
-
-TEST(CircularDeque, EqualsInitializerList) {
- circular_deque<int> q;
- EXPECT_TRUE(q.empty());
- q = {1, 2, 3, 4, 5, 6};
- EXPECT_EQ(6u, q.size());
- for (int i = 0; i < 6; i++)
- EXPECT_EQ(i + 1, q[i]);
-}
-
-TEST(CircularDeque, AssignCountValue) {
- circular_deque<int> empty;
- empty.assign(0, 52);
- EXPECT_EQ(0u, empty.size());
-
- circular_deque<int> full;
- size_t count = 13;
- int value = 12345;
- full.assign(count, value);
- EXPECT_EQ(count, full.size());
-
- for (size_t i = 0; i < count; i++)
- EXPECT_EQ(value, full[i]);
-}
-
-TEST(CircularDeque, AssignIterator) {
- int range[8] = {11, 12, 13, 14, 15, 16, 17, 18};
-
- circular_deque<int> empty;
- empty.assign(std::begin(range), std::begin(range));
- EXPECT_TRUE(empty.empty());
-
- circular_deque<int> full;
- full.assign(std::begin(range), std::end(range));
- EXPECT_EQ(8u, full.size());
- for (size_t i = 0; i < 8; i++)
- EXPECT_EQ(range[i], full[i]);
-}
-
-TEST(CircularDeque, AssignInitializerList) {
- circular_deque<int> empty;
- empty.assign({});
- EXPECT_TRUE(empty.empty());
-
- circular_deque<int> full;
- full.assign({11, 12, 13, 14, 15, 16, 17, 18});
- EXPECT_EQ(8u, full.size());
- for (int i = 0; i < 8; i++)
- EXPECT_EQ(11 + i, full[i]);
-}
-
-// Tests [] and .at().
-TEST(CircularDeque, At) {
- circular_deque<int> q = MakeSequence(10);
- CycleTest(q, [](const circular_deque<int>& q, size_t cycle) {
- size_t expected_size = 10;
- EXPECT_EQ(expected_size, q.size());
-
- // A sequence of 0's.
- size_t index = 0;
- size_t num_zeros = std::min(expected_size, cycle);
- for (size_t i = 0; i < num_zeros; i++, index++) {
- EXPECT_EQ(0, q[index]);
- EXPECT_EQ(0, q.at(index));
- }
-
- // Followed by a sequence of increasing ints.
- size_t num_ints = expected_size - num_zeros;
- for (int i = 0; i < static_cast<int>(num_ints); i++, index++) {
- EXPECT_EQ(i, q[index]);
- EXPECT_EQ(i, q.at(index));
- }
- });
-}
-
-// This also tests the copy constructor with lots of different types of
-// input configurations.
-TEST(CircularDeque, FrontBackPushPop) {
- circular_deque<int> q = MakeSequence(10);
-
- int expected_front = 0;
- int expected_back = 9;
-
- // Go in one direction.
- for (int i = 0; i < 100; i++) {
- const circular_deque<int> const_q(q);
-
- EXPECT_EQ(expected_front, q.front());
- EXPECT_EQ(expected_back, q.back());
- EXPECT_EQ(expected_front, const_q.front());
- EXPECT_EQ(expected_back, const_q.back());
-
- expected_front++;
- expected_back++;
-
- q.pop_front();
- q.push_back(expected_back);
- }
-
- // Go back in reverse.
- for (int i = 0; i < 100; i++) {
- const circular_deque<int> const_q(q);
-
- EXPECT_EQ(expected_front, q.front());
- EXPECT_EQ(expected_back, q.back());
- EXPECT_EQ(expected_front, const_q.front());
- EXPECT_EQ(expected_back, const_q.back());
-
- expected_front--;
- expected_back--;
-
- q.pop_back();
- q.push_front(expected_front);
- }
-}
-
-TEST(CircularDeque, ReallocateWithSplitBuffer) {
- // Tests reallocating a deque with an internal buffer that looks like this:
- // 4 5 x x 0 1 2 3
- // end-^ ^-begin
- circular_deque<int> q;
- q.reserve(7); // Internal buffer is always 1 larger than requested.
- q.push_back(-1);
- q.push_back(-1);
- q.push_back(-1);
- q.push_back(-1);
- q.push_back(0);
- q.pop_front();
- q.pop_front();
- q.pop_front();
- q.pop_front();
- q.push_back(1);
- q.push_back(2);
- q.push_back(3);
- q.push_back(4);
- q.push_back(5);
-
- q.shrink_to_fit();
- EXPECT_EQ(6u, q.size());
-
- EXPECT_EQ(0, q[0]);
- EXPECT_EQ(1, q[1]);
- EXPECT_EQ(2, q[2]);
- EXPECT_EQ(3, q[3]);
- EXPECT_EQ(4, q[4]);
- EXPECT_EQ(5, q[5]);
-}
-
-TEST(CircularDeque, Swap) {
- circular_deque<int> a = MakeSequence(10);
- circular_deque<int> b = MakeSequence(100);
-
- a.swap(b);
- EXPECT_EQ(100u, a.size());
- for (int i = 0; i < 100; i++)
- EXPECT_EQ(i, a[i]);
-
- EXPECT_EQ(10u, b.size());
- for (int i = 0; i < 10; i++)
- EXPECT_EQ(i, b[i]);
-}
-
-TEST(CircularDeque, Iteration) {
- circular_deque<int> q = MakeSequence(10);
-
- int expected_front = 0;
- int expected_back = 9;
-
- // This loop causes various combinations of begin and end to be tested.
- for (int i = 0; i < 30; i++) {
- // Range-based for loop going forward.
- int current_expected = expected_front;
- for (int cur : q) {
- EXPECT_EQ(current_expected, cur);
- current_expected++;
- }
-
- // Manually test reverse iterators.
- current_expected = expected_back;
- for (auto cur = q.crbegin(); cur < q.crend(); cur++) {
- EXPECT_EQ(current_expected, *cur);
- current_expected--;
- }
-
- expected_front++;
- expected_back++;
-
- q.pop_front();
- q.push_back(expected_back);
- }
-
- // Go back in reverse.
- for (int i = 0; i < 100; i++) {
- const circular_deque<int> const_q(q);
-
- EXPECT_EQ(expected_front, q.front());
- EXPECT_EQ(expected_back, q.back());
- EXPECT_EQ(expected_front, const_q.front());
- EXPECT_EQ(expected_back, const_q.back());
-
- expected_front--;
- expected_back--;
-
- q.pop_back();
- q.push_front(expected_front);
- }
-}
-
-TEST(CircularDeque, IteratorComparisons) {
- circular_deque<int> q = MakeSequence(10);
-
- // This loop causes various combinations of begin and end to be tested.
- for (int i = 0; i < 30; i++) {
- EXPECT_LT(q.begin(), q.end());
- EXPECT_LE(q.begin(), q.end());
- EXPECT_LE(q.begin(), q.begin());
-
- EXPECT_GT(q.end(), q.begin());
- EXPECT_GE(q.end(), q.begin());
- EXPECT_GE(q.end(), q.end());
-
- EXPECT_EQ(q.begin(), q.begin());
- EXPECT_NE(q.begin(), q.end());
-
- q.push_front(10);
- q.pop_back();
- }
-}
-
-TEST(CircularDeque, IteratorIncDec) {
- circular_deque<int> q;
-
- // No-op offset computations with no capacity.
- EXPECT_EQ(q.end(), q.end() + 0);
- EXPECT_EQ(q.end(), q.end() - 0);
-
- q = MakeSequence(10);
-
- // Mutable preincrement, predecrement.
- {
- circular_deque<int>::iterator it = q.begin();
- circular_deque<int>::iterator op_result = ++it;
- EXPECT_EQ(1, *op_result);
- EXPECT_EQ(1, *it);
-
- op_result = --it;
- EXPECT_EQ(0, *op_result);
- EXPECT_EQ(0, *it);
- }
-
- // Const preincrement, predecrement.
- {
- circular_deque<int>::const_iterator it = q.begin();
- circular_deque<int>::const_iterator op_result = ++it;
- EXPECT_EQ(1, *op_result);
- EXPECT_EQ(1, *it);
-
- op_result = --it;
- EXPECT_EQ(0, *op_result);
- EXPECT_EQ(0, *it);
- }
-
- // Mutable postincrement, postdecrement.
- {
- circular_deque<int>::iterator it = q.begin();
- circular_deque<int>::iterator op_result = it++;
- EXPECT_EQ(0, *op_result);
- EXPECT_EQ(1, *it);
-
- op_result = it--;
- EXPECT_EQ(1, *op_result);
- EXPECT_EQ(0, *it);
- }
-
- // Const postincrement, postdecrement.
- {
- circular_deque<int>::const_iterator it = q.begin();
- circular_deque<int>::const_iterator op_result = it++;
- EXPECT_EQ(0, *op_result);
- EXPECT_EQ(1, *it);
-
- op_result = it--;
- EXPECT_EQ(1, *op_result);
- EXPECT_EQ(0, *it);
- }
-}
-
-TEST(CircularDeque, IteratorIntegerOps) {
- circular_deque<int> q = MakeSequence(10);
-
- int expected_front = 0;
- int expected_back = 9;
-
- for (int i = 0; i < 30; i++) {
- EXPECT_EQ(0, q.begin() - q.begin());
- EXPECT_EQ(0, q.end() - q.end());
- EXPECT_EQ(q.size(), static_cast<size_t>(q.end() - q.begin()));
-
- // +=
- circular_deque<int>::iterator eight = q.begin();
- eight += 8;
- EXPECT_EQ(8, eight - q.begin());
- EXPECT_EQ(expected_front + 8, *eight);
-
- // -=
- eight -= 8;
- EXPECT_EQ(q.begin(), eight);
-
- // +
- eight = eight + 8;
- EXPECT_EQ(8, eight - q.begin());
-
- // -
- eight = eight - 8;
- EXPECT_EQ(q.begin(), eight);
-
- expected_front++;
- expected_back++;
-
- q.pop_front();
- q.push_back(expected_back);
- }
-}
-
-TEST(CircularDeque, IteratorArrayAccess) {
- circular_deque<int> q = MakeSequence(10);
-
- circular_deque<int>::iterator begin = q.begin();
- EXPECT_EQ(0, begin[0]);
- EXPECT_EQ(9, begin[9]);
-
- circular_deque<int>::iterator end = q.end();
- EXPECT_EQ(0, end[-10]);
- EXPECT_EQ(9, end[-1]);
-
- begin[0] = 100;
- EXPECT_EQ(100, end[-10]);
-}
-
-TEST(CircularDeque, ReverseIterator) {
- circular_deque<int> q;
- q.push_back(4);
- q.push_back(3);
- q.push_back(2);
- q.push_back(1);
-
- circular_deque<int>::reverse_iterator iter = q.rbegin();
- EXPECT_EQ(1, *iter);
- iter++;
- EXPECT_EQ(2, *iter);
- ++iter;
- EXPECT_EQ(3, *iter);
- iter++;
- EXPECT_EQ(4, *iter);
- ++iter;
- EXPECT_EQ(q.rend(), iter);
-}
-
-TEST(CircularDeque, CapacityReserveShrink) {
- circular_deque<int> q;
-
- // A default constructed queue should have no capacity since it should waste
- // no space.
- EXPECT_TRUE(q.empty());
- EXPECT_EQ(0u, q.size());
- EXPECT_EQ(0u, q.capacity());
-
- size_t new_capacity = 100;
- q.reserve(new_capacity);
- EXPECT_EQ(new_capacity, q.capacity());
-
- // Adding that many items should not cause a resize.
- for (size_t i = 0; i < new_capacity; i++)
- q.push_back(i);
- EXPECT_EQ(new_capacity, q.size());
- EXPECT_EQ(new_capacity, q.capacity());
-
- // Shrink to fit to a smaller size.
- size_t capacity_2 = new_capacity / 2;
- q.resize(capacity_2);
- q.shrink_to_fit();
- EXPECT_EQ(capacity_2, q.size());
- EXPECT_EQ(capacity_2, q.capacity());
-}
-
-TEST(CircularDeque, CapacityAutoShrink) {
- size_t big_size = 1000u;
- circular_deque<int> q;
- q.resize(big_size);
-
- size_t big_capacity = q.capacity();
-
- // Delete 3/4 of the items.
- for (size_t i = 0; i < big_size / 4 * 3; i++)
- q.pop_back();
-
- // The capacity should have shrunk by deleting that many items.
- size_t medium_capacity = q.capacity();
- EXPECT_GT(big_capacity, medium_capacity);
-
- // Using resize to shrink should keep some extra capacity.
- q.resize(1);
- EXPECT_LT(1u, q.capacity());
-
- q.resize(0);
- EXPECT_LT(0u, q.capacity());
-
- // Using clear() should delete everything.
- q.clear();
- EXPECT_EQ(0u, q.capacity());
-}
-
-TEST(CircularDeque, ClearAndEmpty) {
- circular_deque<int> q;
- EXPECT_TRUE(q.empty());
-
- q.resize(10);
- EXPECT_EQ(10u, q.size());
- EXPECT_FALSE(q.empty());
-
- q.clear();
- EXPECT_EQ(0u, q.size());
- EXPECT_TRUE(q.empty());
-
- // clear() also should reset the capacity.
- EXPECT_EQ(0u, q.capacity());
-}
-
-TEST(CircularDeque, Resize) {
- circular_deque<int> q;
-
- // Resize with default constructor.
- size_t first_size = 10;
- q.resize(first_size);
- EXPECT_EQ(first_size, q.size());
- for (size_t i = 0; i < first_size; i++)
- EXPECT_EQ(0, q[i]);
-
- // Resize with different value.
- size_t second_expand = 10;
- q.resize(first_size + second_expand, 3);
- EXPECT_EQ(first_size + second_expand, q.size());
- for (size_t i = 0; i < first_size; i++)
- EXPECT_EQ(0, q[i]);
- for (size_t i = 0; i < second_expand; i++)
- EXPECT_EQ(3, q[i + first_size]);
-
- // Erase from the end and add to the beginning so resize is forced to cross
- // a circular buffer wrap boundary.
- q.shrink_to_fit();
- for (int i = 0; i < 5; i++) {
- q.pop_back();
- q.push_front(6);
- }
- q.resize(10);
-
- EXPECT_EQ(6, q[0]);
- EXPECT_EQ(6, q[1]);
- EXPECT_EQ(6, q[2]);
- EXPECT_EQ(6, q[3]);
- EXPECT_EQ(6, q[4]);
- EXPECT_EQ(0, q[5]);
- EXPECT_EQ(0, q[6]);
- EXPECT_EQ(0, q[7]);
- EXPECT_EQ(0, q[8]);
- EXPECT_EQ(0, q[9]);
-}
-
-// Tests destructor behavior of resize.
-TEST(CircularDeque, ResizeDelete) {
- int counter = 0;
- circular_deque<DestructorCounter> q;
- q.resize(10, DestructorCounter(&counter));
- // The one temporary when calling resize() should be deleted, that's it.
- EXPECT_EQ(1, counter);
-
- // The loops below assume the capacity will be set by resize().
- EXPECT_EQ(10u, q.capacity());
-
- // Delete some via resize(). This is done so that the wasted items are
- // still greater than the size() so that auto-shrinking is not triggered
- // (which will mess up our destructor counting).
- counter = 0;
- q.resize(8, DestructorCounter(&counter));
- // 2 deleted ones + the one temporary in the resize() call.
- EXPECT_EQ(3, counter);
-
- // Cycle through some items so two items will cross the boundary in the
- // 11-item buffer (one more than the capacity).
- // Before: x x x x x x x x . . .
- // After: x . . . x x x x x x x
- counter = 0;
- for (int i = 0; i < 4; i++) {
- q.emplace_back(&counter);
- q.pop_front();
- }
- EXPECT_EQ(4, counter); // Loop should have deleted 7 items.
-
- // Delete two items with resize, these should be on either side of the
- // buffer wrap point.
- counter = 0;
- q.resize(6, DestructorCounter(&counter));
- // 2 deleted ones + the one temporary in the resize() call.
- EXPECT_EQ(3, counter);
-}
-
-TEST(CircularDeque, InsertEraseSingle) {
- circular_deque<int> q;
- q.push_back(1);
- q.push_back(2);
-
- // Insert at the beginning.
- auto result = q.insert(q.begin(), 0);
- EXPECT_EQ(q.begin(), result);
- EXPECT_EQ(3u, q.size());
- EXPECT_EQ(0, q[0]);
- EXPECT_EQ(1, q[1]);
- EXPECT_EQ(2, q[2]);
-
- // Erase at the beginning.
- result = q.erase(q.begin());
- EXPECT_EQ(q.begin(), result);
- EXPECT_EQ(2u, q.size());
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(2, q[1]);
-
- // Insert at the end.
- result = q.insert(q.end(), 3);
- EXPECT_EQ(q.end() - 1, result);
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(2, q[1]);
- EXPECT_EQ(3, q[2]);
-
- // Erase at the end.
- result = q.erase(q.end() - 1);
- EXPECT_EQ(q.end(), result);
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(2, q[1]);
-
- // Insert in the middle.
- result = q.insert(q.begin() + 1, 10);
- EXPECT_EQ(q.begin() + 1, result);
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(10, q[1]);
- EXPECT_EQ(2, q[2]);
-
- // Erase in the middle.
- result = q.erase(q.begin() + 1);
- EXPECT_EQ(q.begin() + 1, result);
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(2, q[1]);
-}
-
-TEST(CircularDeque, InsertFill) {
- circular_deque<int> q;
-
- // Fill when empty.
- q.insert(q.begin(), 2, 1);
-
- // 0's at the beginning.
- q.insert(q.begin(), 2, 0);
-
- // 50's in the middle (now at offset 3).
- q.insert(q.begin() + 3, 2, 50);
-
- // 200's at the end.
- q.insert(q.end(), 2, 200);
-
- ASSERT_EQ(8u, q.size());
- EXPECT_EQ(0, q[0]);
- EXPECT_EQ(0, q[1]);
- EXPECT_EQ(1, q[2]);
- EXPECT_EQ(50, q[3]);
- EXPECT_EQ(50, q[4]);
- EXPECT_EQ(1, q[5]);
- EXPECT_EQ(200, q[6]);
- EXPECT_EQ(200, q[7]);
-}
-
-TEST(CircularDeque, InsertEraseRange) {
- circular_deque<int> q;
-
- // Erase nothing from an empty deque should work.
- q.erase(q.begin(), q.end());
-
- // Loop index used below to shift the used items in the buffer.
- for (int i = 0; i < 10; i++) {
- circular_deque<int> source;
-
- // Fill empty range.
- q.insert(q.begin(), source.begin(), source.end());
-
- // Have some stuff to insert.
- source.push_back(1);
- source.push_back(2);
-
- q.insert(q.begin(), source.begin(), source.end());
-
- // Shift the used items in the buffer by i which will place the two used
- // elements in different places in the buffer each time through this loop.
- for (int shift_i = 0; shift_i < i; shift_i++) {
- q.push_back(0);
- q.pop_front();
- }
-
- // Set the two items to notable values so we can check for them later.
- ASSERT_EQ(2u, q.size());
- q[0] = 100;
- q[1] = 101;
-
- // Insert at the beginning, middle (now at offset 3), and end.
- q.insert(q.begin(), source.begin(), source.end());
- q.insert(q.begin() + 3, source.begin(), source.end());
- q.insert(q.end(), source.begin(), source.end());
-
- ASSERT_EQ(8u, q.size());
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(2, q[1]);
- EXPECT_EQ(100, q[2]); // First inserted one.
- EXPECT_EQ(1, q[3]);
- EXPECT_EQ(2, q[4]);
- EXPECT_EQ(101, q[5]); // First inserted second one.
- EXPECT_EQ(1, q[6]);
- EXPECT_EQ(2, q[7]);
-
- // Now erase the inserted ranges. Try each subsection also with no items
- // being erased, which should be a no-op.
- auto result = q.erase(q.begin(), q.begin()); // No-op.
- EXPECT_EQ(q.begin(), result);
- result = q.erase(q.begin(), q.begin() + 2);
- EXPECT_EQ(q.begin(), result);
-
- result = q.erase(q.begin() + 1, q.begin() + 1); // No-op.
- EXPECT_EQ(q.begin() + 1, result);
- result = q.erase(q.begin() + 1, q.begin() + 3);
- EXPECT_EQ(q.begin() + 1, result);
-
- result = q.erase(q.end() - 2, q.end() - 2); // No-op.
- EXPECT_EQ(q.end() - 2, result);
- result = q.erase(q.end() - 2, q.end());
- EXPECT_EQ(q.end(), result);
-
- ASSERT_EQ(2u, q.size());
- EXPECT_EQ(100, q[0]);
- EXPECT_EQ(101, q[1]);
-
- // Erase everything.
- result = q.erase(q.begin(), q.end());
- EXPECT_EQ(q.end(), result);
- EXPECT_TRUE(q.empty());
- }
-}
-
-TEST(CircularDeque, EmplaceMoveOnly) {
- int values[] = {1, 3};
- circular_deque<MoveOnlyInt> q(std::begin(values), std::end(values));
-
- q.emplace(q.begin(), MoveOnlyInt(0));
- q.emplace(q.begin() + 2, MoveOnlyInt(2));
- q.emplace(q.end(), MoveOnlyInt(4));
-
- ASSERT_EQ(5u, q.size());
- EXPECT_EQ(0, q[0].data());
- EXPECT_EQ(1, q[1].data());
- EXPECT_EQ(2, q[2].data());
- EXPECT_EQ(3, q[3].data());
- EXPECT_EQ(4, q[4].data());
-}
-
-TEST(CircularDeque, EmplaceFrontBackReturnsReference) {
- circular_deque<int> q;
- q.reserve(2);
-
- int& front = q.emplace_front(1);
- int& back = q.emplace_back(2);
- ASSERT_EQ(2u, q.size());
- EXPECT_EQ(1, q[0]);
- EXPECT_EQ(2, q[1]);
-
- EXPECT_EQ(&front, &q.front());
- EXPECT_EQ(&back, &q.back());
-
- front = 3;
- back = 4;
-
- ASSERT_EQ(2u, q.size());
- EXPECT_EQ(3, q[0]);
- EXPECT_EQ(4, q[1]);
-
- EXPECT_EQ(&front, &q.front());
- EXPECT_EQ(&back, &q.back());
-}
-
-/*
-This test should assert in a debug build. It tries to dereference an iterator
-after mutating the container. Uncomment to double-check that this works.
-TEST(CircularDeque, UseIteratorAfterMutate) {
- circular_deque<int> q;
- q.push_back(0);
-
- auto old_begin = q.begin();
- EXPECT_EQ(0, *old_begin);
-
- q.push_back(1);
- EXPECT_EQ(0, *old_begin); // Should DCHECK.
-}
-*/
-
-} // namespace base
diff --git a/base/containers/flat_map_unittest.cc b/base/containers/flat_map_unittest.cc
deleted file mode 100644
index 87958bd..0000000
--- 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 4596975..0000000
--- 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 5b788d5..0000000
--- 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 6072e5d..0000000
--- 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_unittest.cc b/base/containers/id_map_unittest.cc
deleted file mode 100644
index 346b69f..0000000
--- 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 8e547ba..0000000
--- 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 28e6f0d..0000000
--- 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 6561851..0000000
--- 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/span_unittest.cc b/base/containers/span_unittest.cc
deleted file mode 100644
index de5e401..0000000
--- a/base/containers/span_unittest.cc
+++ /dev/null
@@ -1,1170 +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/span.h"
-
-#include <stdint.h>
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-using ::testing::Eq;
-using ::testing::Pointwise;
-
-namespace base {
-
-TEST(SpanTest, DefaultConstructor) {
- span<int> dynamic_span;
- EXPECT_EQ(nullptr, dynamic_span.data());
- EXPECT_EQ(0u, dynamic_span.size());
-
- constexpr span<int, 0> static_span;
- static_assert(nullptr == static_span.data(), "");
- static_assert(0u == static_span.size(), "");
-}
-
-TEST(SpanTest, ConstructFromDataAndSize) {
- constexpr span<int> empty_span(nullptr, 0);
- EXPECT_TRUE(empty_span.empty());
- EXPECT_EQ(nullptr, empty_span.data());
-
- std::vector<int> vector = {1, 1, 2, 3, 5, 8};
-
- span<int> dynamic_span(vector.data(), vector.size());
- EXPECT_EQ(vector.data(), dynamic_span.data());
- EXPECT_EQ(vector.size(), dynamic_span.size());
-
- for (size_t i = 0; i < dynamic_span.size(); ++i)
- EXPECT_EQ(vector[i], dynamic_span[i]);
-
- span<int, 6> static_span(vector.data(), vector.size());
- EXPECT_EQ(vector.data(), static_span.data());
- EXPECT_EQ(vector.size(), static_span.size());
-
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(vector[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromPointerPair) {
- constexpr span<int> empty_span(nullptr, nullptr);
- EXPECT_TRUE(empty_span.empty());
- EXPECT_EQ(nullptr, empty_span.data());
-
- std::vector<int> vector = {1, 1, 2, 3, 5, 8};
-
- span<int> dynamic_span(vector.data(), vector.data() + vector.size() / 2);
- EXPECT_EQ(vector.data(), dynamic_span.data());
- EXPECT_EQ(vector.size() / 2, dynamic_span.size());
-
- for (size_t i = 0; i < dynamic_span.size(); ++i)
- EXPECT_EQ(vector[i], dynamic_span[i]);
-
- span<int, 3> static_span(vector.data(), vector.data() + vector.size() / 2);
- EXPECT_EQ(vector.data(), static_span.data());
- EXPECT_EQ(vector.size() / 2, static_span.size());
-
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(vector[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromConstexprArray) {
- static constexpr int kArray[] = {5, 4, 3, 2, 1};
-
- constexpr span<const int> dynamic_span(kArray);
- static_assert(kArray == dynamic_span.data(), "");
- static_assert(base::size(kArray) == dynamic_span.size(), "");
-
- static_assert(kArray[0] == dynamic_span[0], "");
- static_assert(kArray[1] == dynamic_span[1], "");
- static_assert(kArray[2] == dynamic_span[2], "");
- static_assert(kArray[3] == dynamic_span[3], "");
- static_assert(kArray[4] == dynamic_span[4], "");
-
- constexpr span<const int, base::size(kArray)> static_span(kArray);
- static_assert(kArray == static_span.data(), "");
- static_assert(base::size(kArray) == static_span.size(), "");
-
- static_assert(kArray[0] == static_span[0], "");
- static_assert(kArray[1] == static_span[1], "");
- static_assert(kArray[2] == static_span[2], "");
- static_assert(kArray[3] == static_span[3], "");
- static_assert(kArray[4] == static_span[4], "");
-}
-
-TEST(SpanTest, ConstructFromArray) {
- int array[] = {5, 4, 3, 2, 1};
-
- span<const int> const_span(array);
- EXPECT_EQ(array, const_span.data());
- EXPECT_EQ(arraysize(array), const_span.size());
- for (size_t i = 0; i < const_span.size(); ++i)
- EXPECT_EQ(array[i], const_span[i]);
-
- span<int> dynamic_span(array);
- EXPECT_EQ(array, dynamic_span.data());
- EXPECT_EQ(base::size(array), dynamic_span.size());
- for (size_t i = 0; i < dynamic_span.size(); ++i)
- EXPECT_EQ(array[i], dynamic_span[i]);
-
- span<int, base::size(array)> static_span(array);
- EXPECT_EQ(array, static_span.data());
- EXPECT_EQ(base::size(array), static_span.size());
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(array[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromStdArray) {
- // Note: Constructing a constexpr span from a constexpr std::array does not
- // work prior to C++17 due to non-constexpr std::array::data.
- std::array<int, 5> array = {{5, 4, 3, 2, 1}};
-
- span<const int> const_span(array);
- EXPECT_EQ(array.data(), const_span.data());
- EXPECT_EQ(array.size(), const_span.size());
- for (size_t i = 0; i < const_span.size(); ++i)
- EXPECT_EQ(array[i], const_span[i]);
-
- span<int> dynamic_span(array);
- EXPECT_EQ(array.data(), dynamic_span.data());
- EXPECT_EQ(array.size(), dynamic_span.size());
- for (size_t i = 0; i < dynamic_span.size(); ++i)
- EXPECT_EQ(array[i], dynamic_span[i]);
-
- span<int, base::size(array)> static_span(array);
- EXPECT_EQ(array.data(), static_span.data());
- EXPECT_EQ(array.size(), static_span.size());
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(array[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromInitializerList) {
- std::initializer_list<int> il = {1, 1, 2, 3, 5, 8};
-
- span<const int> const_span(il);
- EXPECT_EQ(il.begin(), const_span.data());
- EXPECT_EQ(il.size(), const_span.size());
-
- for (size_t i = 0; i < const_span.size(); ++i)
- EXPECT_EQ(il.begin()[i], const_span[i]);
-
- span<const int, 6> static_span(il);
- EXPECT_EQ(il.begin(), static_span.data());
- EXPECT_EQ(il.size(), static_span.size());
-
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(il.begin()[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromStdString) {
- std::string str = "foobar";
-
- span<const char> const_span(str);
- EXPECT_EQ(str.data(), const_span.data());
- EXPECT_EQ(str.size(), const_span.size());
-
- for (size_t i = 0; i < const_span.size(); ++i)
- EXPECT_EQ(str[i], const_span[i]);
-
- span<char> dynamic_span(str);
- EXPECT_EQ(str.data(), dynamic_span.data());
- EXPECT_EQ(str.size(), dynamic_span.size());
-
- for (size_t i = 0; i < dynamic_span.size(); ++i)
- EXPECT_EQ(str[i], dynamic_span[i]);
-
- span<char, 6> static_span(str);
- EXPECT_EQ(str.data(), static_span.data());
- EXPECT_EQ(str.size(), static_span.size());
-
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(str[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromConstContainer) {
- const std::vector<int> vector = {1, 1, 2, 3, 5, 8};
-
- span<const int> const_span(vector);
- EXPECT_EQ(vector.data(), const_span.data());
- EXPECT_EQ(vector.size(), const_span.size());
-
- for (size_t i = 0; i < const_span.size(); ++i)
- EXPECT_EQ(vector[i], const_span[i]);
-
- span<const int, 6> static_span(vector);
- EXPECT_EQ(vector.data(), static_span.data());
- EXPECT_EQ(vector.size(), static_span.size());
-
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(vector[i], static_span[i]);
-}
-
-TEST(SpanTest, ConstructFromContainer) {
- std::vector<int> vector = {1, 1, 2, 3, 5, 8};
-
- span<const int> const_span(vector);
- EXPECT_EQ(vector.data(), const_span.data());
- EXPECT_EQ(vector.size(), const_span.size());
-
- for (size_t i = 0; i < const_span.size(); ++i)
- EXPECT_EQ(vector[i], const_span[i]);
-
- span<int> dynamic_span(vector);
- EXPECT_EQ(vector.data(), dynamic_span.data());
- EXPECT_EQ(vector.size(), dynamic_span.size());
-
- for (size_t i = 0; i < dynamic_span.size(); ++i)
- EXPECT_EQ(vector[i], dynamic_span[i]);
-
- span<int, 6> static_span(vector);
- EXPECT_EQ(vector.data(), static_span.data());
- EXPECT_EQ(vector.size(), static_span.size());
-
- for (size_t i = 0; i < static_span.size(); ++i)
- EXPECT_EQ(vector[i], static_span[i]);
-}
-
-TEST(SpanTest, ConvertNonConstIntegralToConst) {
- std::vector<int> vector = {1, 1, 2, 3, 5, 8};
-
- span<int> int_span(vector.data(), vector.size());
- span<const int> const_span(int_span);
- EXPECT_THAT(const_span, Pointwise(Eq(), int_span));
-
- span<int, 6> static_int_span(vector.data(), vector.size());
- span<const int, 6> static_const_span(static_int_span);
- EXPECT_THAT(static_const_span, Pointwise(Eq(), static_int_span));
-}
-
-TEST(SpanTest, ConvertNonConstPointerToConst) {
- auto a = std::make_unique<int>(11);
- auto b = std::make_unique<int>(22);
- auto c = std::make_unique<int>(33);
- std::vector<int*> vector = {a.get(), b.get(), c.get()};
-
- span<int*> non_const_pointer_span(vector);
- EXPECT_THAT(non_const_pointer_span, Pointwise(Eq(), vector));
- span<int* const> const_pointer_span(non_const_pointer_span);
- EXPECT_THAT(const_pointer_span, Pointwise(Eq(), non_const_pointer_span));
- // Note: no test for conversion from span<int> to span<const int*>, since that
- // would imply a conversion from int** to const int**, which is unsafe.
- //
- // Note: no test for conversion from span<int*> to span<const int* const>,
- // due to CWG Defect 330:
- // http://open-std.org/JTC1/SC22/WG21/docs/cwg_defects.html#330
-
- span<int*, 3> static_non_const_pointer_span(vector);
- EXPECT_THAT(static_non_const_pointer_span, Pointwise(Eq(), vector));
- span<int* const, 3> static_const_pointer_span(static_non_const_pointer_span);
- EXPECT_THAT(static_const_pointer_span,
- Pointwise(Eq(), static_non_const_pointer_span));
-}
-
-TEST(SpanTest, ConvertBetweenEquivalentTypes) {
- std::vector<int32_t> vector = {2, 4, 8, 16, 32};
-
- span<int32_t> int32_t_span(vector);
- span<int> converted_span(int32_t_span);
- EXPECT_EQ(int32_t_span, converted_span);
-
- span<int32_t, 5> static_int32_t_span(vector);
- span<int, 5> static_converted_span(static_int32_t_span);
- EXPECT_EQ(static_int32_t_span, static_converted_span);
-}
-
-TEST(SpanTest, TemplatedFirst) {
- static constexpr int array[] = {1, 2, 3};
- constexpr span<const int, 3> span(array);
-
- {
- constexpr auto subspan = span.first<0>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(0u == subspan.size(), "");
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- constexpr auto subspan = span.first<1>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(1u == subspan.size(), "");
- static_assert(1u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- }
-
- {
- constexpr auto subspan = span.first<2>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(2u == subspan.size(), "");
- static_assert(2u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- static_assert(2 == subspan[1], "");
- }
-
- {
- constexpr auto subspan = span.first<3>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(3u == subspan.size(), "");
- static_assert(3u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- static_assert(2 == subspan[1], "");
- static_assert(3 == subspan[2], "");
- }
-}
-
-TEST(SpanTest, TemplatedLast) {
- static constexpr int array[] = {1, 2, 3};
- constexpr span<const int, 3> span(array);
-
- {
- constexpr auto subspan = span.last<0>();
- static_assert(span.data() + 3 == subspan.data(), "");
- static_assert(0u == subspan.size(), "");
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- constexpr auto subspan = span.last<1>();
- static_assert(span.data() + 2 == subspan.data(), "");
- static_assert(1u == subspan.size(), "");
- static_assert(1u == decltype(subspan)::extent, "");
- static_assert(3 == subspan[0], "");
- }
-
- {
- constexpr auto subspan = span.last<2>();
- static_assert(span.data() + 1 == subspan.data(), "");
- static_assert(2u == subspan.size(), "");
- static_assert(2u == decltype(subspan)::extent, "");
- static_assert(2 == subspan[0], "");
- static_assert(3 == subspan[1], "");
- }
-
- {
- constexpr auto subspan = span.last<3>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(3u == subspan.size(), "");
- static_assert(3u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- static_assert(2 == subspan[1], "");
- static_assert(3 == subspan[2], "");
- }
-}
-
-TEST(SpanTest, TemplatedSubspan) {
- static constexpr int array[] = {1, 2, 3};
- constexpr span<const int, 3> span(array);
-
- {
- constexpr auto subspan = span.subspan<0>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(3u == subspan.size(), "");
- static_assert(3u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- static_assert(2 == subspan[1], "");
- static_assert(3 == subspan[2], "");
- }
-
- {
- constexpr auto subspan = span.subspan<1>();
- static_assert(span.data() + 1 == subspan.data(), "");
- static_assert(2u == subspan.size(), "");
- static_assert(2u == decltype(subspan)::extent, "");
- static_assert(2 == subspan[0], "");
- static_assert(3 == subspan[1], "");
- }
-
- {
- constexpr auto subspan = span.subspan<2>();
- static_assert(span.data() + 2 == subspan.data(), "");
- static_assert(1u == subspan.size(), "");
- static_assert(1u == decltype(subspan)::extent, "");
- static_assert(3 == subspan[0], "");
- }
-
- {
- constexpr auto subspan = span.subspan<3>();
- static_assert(span.data() + 3 == subspan.data(), "");
- static_assert(0u == subspan.size(), "");
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- constexpr auto subspan = span.subspan<0, 0>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(0u == subspan.size(), "");
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- constexpr auto subspan = span.subspan<1, 0>();
- static_assert(span.data() + 1 == subspan.data(), "");
- static_assert(0u == subspan.size(), "");
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- constexpr auto subspan = span.subspan<2, 0>();
- static_assert(span.data() + 2 == subspan.data(), "");
- static_assert(0u == subspan.size(), "");
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- constexpr auto subspan = span.subspan<0, 1>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(1u == subspan.size(), "");
- static_assert(1u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- }
-
- {
- constexpr auto subspan = span.subspan<1, 1>();
- static_assert(span.data() + 1 == subspan.data(), "");
- static_assert(1u == subspan.size(), "");
- static_assert(1u == decltype(subspan)::extent, "");
- static_assert(2 == subspan[0], "");
- }
-
- {
- constexpr auto subspan = span.subspan<2, 1>();
- static_assert(span.data() + 2 == subspan.data(), "");
- static_assert(1u == subspan.size(), "");
- static_assert(1u == decltype(subspan)::extent, "");
- static_assert(3 == subspan[0], "");
- }
-
- {
- constexpr auto subspan = span.subspan<0, 2>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(2u == subspan.size(), "");
- static_assert(2u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- static_assert(2 == subspan[1], "");
- }
-
- {
- constexpr auto subspan = span.subspan<1, 2>();
- static_assert(span.data() + 1 == subspan.data(), "");
- static_assert(2u == subspan.size(), "");
- static_assert(2u == decltype(subspan)::extent, "");
- static_assert(2 == subspan[0], "");
- static_assert(3 == subspan[1], "");
- }
-
- {
- constexpr auto subspan = span.subspan<0, 3>();
- static_assert(span.data() == subspan.data(), "");
- static_assert(3u == subspan.size(), "");
- static_assert(3u == decltype(subspan)::extent, "");
- static_assert(1 == subspan[0], "");
- static_assert(2 == subspan[1], "");
- static_assert(3 == subspan[2], "");
- }
-}
-
-TEST(SpanTest, TemplatedFirstOnDynamicSpan) {
- int array[] = {1, 2, 3};
- span<const int> span(array);
-
- {
- auto subspan = span.first<0>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(0u, subspan.size());
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- auto subspan = span.first<1>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(1u, subspan.size());
- static_assert(1u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- }
-
- {
- auto subspan = span.first<2>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(2u, subspan.size());
- static_assert(2u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- }
-
- {
- auto subspan = span.first<3>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(3u, subspan.size());
- static_assert(3u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-}
-
-TEST(SpanTest, TemplatedLastOnDynamicSpan) {
- int array[] = {1, 2, 3};
- span<int> span(array);
-
- {
- auto subspan = span.last<0>();
- EXPECT_EQ(span.data() + 3, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- auto subspan = span.last<1>();
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- static_assert(1u == decltype(subspan)::extent, "");
- EXPECT_EQ(3, subspan[0]);
- }
-
- {
- auto subspan = span.last<2>();
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(2u, subspan.size());
- static_assert(2u == decltype(subspan)::extent, "");
- EXPECT_EQ(2, subspan[0]);
- EXPECT_EQ(3, subspan[1]);
- }
-
- {
- auto subspan = span.last<3>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(3u, subspan.size());
- static_assert(3u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-}
-
-TEST(SpanTest, TemplatedSubspanFromDynamicSpan) {
- int array[] = {1, 2, 3};
- span<int, 3> span(array);
-
- {
- auto subspan = span.subspan<0>();
- EXPECT_EQ(span.data(), subspan.data());
- static_assert(3u == decltype(subspan)::extent, "");
- EXPECT_EQ(3u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-
- {
- auto subspan = span.subspan<1>();
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(2u, subspan.size());
- static_assert(2u == decltype(subspan)::extent, "");
- EXPECT_EQ(2, subspan[0]);
- EXPECT_EQ(3, subspan[1]);
- }
-
- {
- auto subspan = span.subspan<2>();
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- static_assert(1u == decltype(subspan)::extent, "");
- EXPECT_EQ(3, subspan[0]);
- }
-
- {
- auto subspan = span.subspan<3>();
- EXPECT_EQ(span.data() + 3, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- auto subspan = span.subspan<0, 0>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(0u, subspan.size());
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- auto subspan = span.subspan<1, 0>();
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- auto subspan = span.subspan<2, 0>();
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- static_assert(0u == decltype(subspan)::extent, "");
- }
-
- {
- auto subspan = span.subspan<0, 1>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(1u, subspan.size());
- static_assert(1u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- }
-
- {
- auto subspan = span.subspan<1, 1>();
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- static_assert(1u == decltype(subspan)::extent, "");
- EXPECT_EQ(2, subspan[0]);
- }
-
- {
- auto subspan = span.subspan<2, 1>();
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- static_assert(1u == decltype(subspan)::extent, "");
- EXPECT_EQ(3, subspan[0]);
- }
-
- {
- auto subspan = span.subspan<0, 2>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(2u, subspan.size());
- static_assert(2u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- }
-
- {
- auto subspan = span.subspan<1, 2>();
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(2u, subspan.size());
- static_assert(2u == decltype(subspan)::extent, "");
- EXPECT_EQ(2, subspan[0]);
- EXPECT_EQ(3, subspan[1]);
- }
-
- {
- auto subspan = span.subspan<0, 3>();
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(3u, subspan.size());
- static_assert(3u == decltype(subspan)::extent, "");
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-}
-
-TEST(SpanTest, First) {
- int array[] = {1, 2, 3};
- span<int> span(array);
-
- {
- auto subspan = span.first(0);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(0u, subspan.size());
- }
-
- {
- auto subspan = span.first(1);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(1u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- }
-
- {
- auto subspan = span.first(2);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(2u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- }
-
- {
- auto subspan = span.first(3);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(3u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-}
-
-TEST(SpanTest, Last) {
- int array[] = {1, 2, 3};
- span<int> span(array);
-
- {
- auto subspan = span.last(0);
- EXPECT_EQ(span.data() + 3, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- }
-
- {
- auto subspan = span.last(1);
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- EXPECT_EQ(3, subspan[0]);
- }
-
- {
- auto subspan = span.last(2);
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(2u, subspan.size());
- EXPECT_EQ(2, subspan[0]);
- EXPECT_EQ(3, subspan[1]);
- }
-
- {
- auto subspan = span.last(3);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(3u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-}
-
-TEST(SpanTest, Subspan) {
- int array[] = {1, 2, 3};
- span<int> span(array);
-
- {
- auto subspan = span.subspan(0);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(3u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-
- {
- auto subspan = span.subspan(1);
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(2u, subspan.size());
- EXPECT_EQ(2, subspan[0]);
- EXPECT_EQ(3, subspan[1]);
- }
-
- {
- auto subspan = span.subspan(2);
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- EXPECT_EQ(3, subspan[0]);
- }
-
- {
- auto subspan = span.subspan(3);
- EXPECT_EQ(span.data() + 3, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- }
-
- {
- auto subspan = span.subspan(0, 0);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(0u, subspan.size());
- }
-
- {
- auto subspan = span.subspan(1, 0);
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- }
-
- {
- auto subspan = span.subspan(2, 0);
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(0u, subspan.size());
- }
-
- {
- auto subspan = span.subspan(0, 1);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(1u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- }
-
- {
- auto subspan = span.subspan(1, 1);
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- EXPECT_EQ(2, subspan[0]);
- }
-
- {
- auto subspan = span.subspan(2, 1);
- EXPECT_EQ(span.data() + 2, subspan.data());
- EXPECT_EQ(1u, subspan.size());
- EXPECT_EQ(3, subspan[0]);
- }
-
- {
- auto subspan = span.subspan(0, 2);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(2u, subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- }
-
- {
- auto subspan = span.subspan(1, 2);
- EXPECT_EQ(span.data() + 1, subspan.data());
- EXPECT_EQ(2u, subspan.size());
- EXPECT_EQ(2, subspan[0]);
- EXPECT_EQ(3, subspan[1]);
- }
-
- {
- auto subspan = span.subspan(0, 3);
- EXPECT_EQ(span.data(), subspan.data());
- EXPECT_EQ(span.size(), subspan.size());
- EXPECT_EQ(1, subspan[0]);
- EXPECT_EQ(2, subspan[1]);
- EXPECT_EQ(3, subspan[2]);
- }
-}
-
-TEST(SpanTest, Size) {
- {
- span<int> span;
- EXPECT_EQ(0u, span.size());
- }
-
- {
- int array[] = {1, 2, 3};
- span<int> span(array);
- EXPECT_EQ(3u, span.size());
- }
-}
-
-TEST(SpanTest, SizeBytes) {
- {
- span<int> span;
- EXPECT_EQ(0u, span.size_bytes());
- }
-
- {
- int array[] = {1, 2, 3};
- span<int> span(array);
- EXPECT_EQ(3u * sizeof(int), span.size_bytes());
- }
-}
-
-TEST(SpanTest, Empty) {
- {
- span<int> span;
- EXPECT_TRUE(span.empty());
- }
-
- {
- int array[] = {1, 2, 3};
- span<int> span(array);
- EXPECT_FALSE(span.empty());
- }
-}
-
-TEST(SpanTest, OperatorAt) {
- static constexpr int kArray[] = {1, 6, 1, 8, 0};
- constexpr span<const int> span(kArray);
-
- static_assert(kArray[0] == span[0], "span[0] does not equal kArray[0]");
- static_assert(kArray[1] == span[1], "span[1] does not equal kArray[1]");
- static_assert(kArray[2] == span[2], "span[2] does not equal kArray[2]");
- static_assert(kArray[3] == span[3], "span[3] does not equal kArray[3]");
- static_assert(kArray[4] == span[4], "span[4] does not equal kArray[4]");
-
- static_assert(kArray[0] == span(0), "span(0) does not equal kArray[0]");
- static_assert(kArray[1] == span(1), "span(1) does not equal kArray[1]");
- static_assert(kArray[2] == span(2), "span(2) does not equal kArray[2]");
- static_assert(kArray[3] == span(3), "span(3) does not equal kArray[3]");
- static_assert(kArray[4] == span(4), "span(4) does not equal kArray[4]");
-}
-
-TEST(SpanTest, Iterator) {
- static constexpr int kArray[] = {1, 6, 1, 8, 0};
- constexpr span<const int> span(kArray);
-
- std::vector<int> results;
- for (int i : span)
- results.emplace_back(i);
- EXPECT_THAT(results, ElementsAre(1, 6, 1, 8, 0));
-}
-
-TEST(SpanTest, ReverseIterator) {
- static constexpr int kArray[] = {1, 6, 1, 8, 0};
- constexpr span<const int> span(kArray);
-
- EXPECT_TRUE(std::equal(std::rbegin(kArray), std::rend(kArray), span.rbegin(),
- span.rend()));
- EXPECT_TRUE(std::equal(std::crbegin(kArray), std::crend(kArray),
- span.crbegin(), span.crend()));
-}
-
-TEST(SpanTest, Equality) {
- static constexpr int kArray1[] = {3, 1, 4, 1, 5};
- static constexpr int kArray2[] = {3, 1, 4, 1, 5};
- constexpr span<const int> span1(kArray1);
- constexpr span<const int, 5> span2(kArray2);
-
- EXPECT_EQ(span1, span2);
-
- static constexpr int kArray3[] = {2, 7, 1, 8, 3};
- constexpr span<const int> span3(kArray3);
-
- EXPECT_FALSE(span1 == span3);
-
- static double kArray4[] = {2.0, 7.0, 1.0, 8.0, 3.0};
- span<double, 5> span4(kArray4);
-
- EXPECT_EQ(span3, span4);
-}
-
-TEST(SpanTest, Inequality) {
- static constexpr int kArray1[] = {2, 3, 5, 7, 11};
- static constexpr int kArray2[] = {1, 4, 6, 8, 9};
- constexpr span<const int> span1(kArray1);
- constexpr span<const int, 5> span2(kArray2);
-
- EXPECT_NE(span1, span2);
-
- static constexpr int kArray3[] = {2, 3, 5, 7, 11};
- constexpr span<const int> span3(kArray3);
-
- EXPECT_FALSE(span1 != span3);
-
- static double kArray4[] = {1.0, 4.0, 6.0, 8.0, 9.0};
- span<double, 5> span4(kArray4);
-
- EXPECT_NE(span3, span4);
-}
-
-TEST(SpanTest, LessThan) {
- static constexpr int kArray1[] = {2, 3, 5, 7, 11};
- static constexpr int kArray2[] = {2, 3, 5, 7, 11, 13};
- constexpr span<const int> span1(kArray1);
- constexpr span<const int, 6> span2(kArray2);
-
- EXPECT_LT(span1, span2);
-
- static constexpr int kArray3[] = {2, 3, 5, 7, 11};
- constexpr span<const int> span3(kArray3);
-
- EXPECT_FALSE(span1 < span3);
-
- static double kArray4[] = {2.0, 3.0, 5.0, 7.0, 11.0, 13.0};
- span<double, 6> span4(kArray4);
-
- EXPECT_LT(span3, span4);
-}
-
-TEST(SpanTest, LessEqual) {
- static constexpr int kArray1[] = {2, 3, 5, 7, 11};
- static constexpr int kArray2[] = {2, 3, 5, 7, 11, 13};
- constexpr span<const int> span1(kArray1);
- constexpr span<const int, 6> span2(kArray2);
-
- EXPECT_LE(span1, span1);
- EXPECT_LE(span1, span2);
-
- static constexpr int kArray3[] = {2, 3, 5, 7, 10};
- constexpr span<const int> span3(kArray3);
-
- EXPECT_FALSE(span1 <= span3);
-
- static double kArray4[] = {2.0, 3.0, 5.0, 7.0, 11.0, 13.0};
- span<double, 6> span4(kArray4);
-
- EXPECT_LE(span3, span4);
-}
-
-TEST(SpanTest, GreaterThan) {
- static constexpr int kArray1[] = {2, 3, 5, 7, 11, 13};
- static constexpr int kArray2[] = {2, 3, 5, 7, 11};
- constexpr span<const int> span1(kArray1);
- constexpr span<const int, 5> span2(kArray2);
-
- EXPECT_GT(span1, span2);
-
- static constexpr int kArray3[] = {2, 3, 5, 7, 11, 13};
- constexpr span<const int> span3(kArray3);
-
- EXPECT_FALSE(span1 > span3);
-
- static double kArray4[] = {2.0, 3.0, 5.0, 7.0, 11.0};
- span<double, 5> span4(kArray4);
-
- EXPECT_GT(span3, span4);
-}
-
-TEST(SpanTest, GreaterEqual) {
- static constexpr int kArray1[] = {2, 3, 5, 7, 11, 13};
- static constexpr int kArray2[] = {2, 3, 5, 7, 11};
- constexpr span<const int> span1(kArray1);
- constexpr span<const int, 5> span2(kArray2);
-
- EXPECT_GE(span1, span1);
- EXPECT_GE(span1, span2);
-
- static constexpr int kArray3[] = {2, 3, 5, 7, 12};
- constexpr span<const int> span3(kArray3);
-
- EXPECT_FALSE(span1 >= span3);
-
- static double kArray4[] = {2.0, 3.0, 5.0, 7.0, 11.0};
- span<double, 5> span4(kArray4);
-
- EXPECT_GE(span3, span4);
-}
-
-TEST(SpanTest, AsBytes) {
- {
- constexpr int kArray[] = {2, 3, 5, 7, 11, 13};
- span<const uint8_t, sizeof(kArray)> bytes_span =
- as_bytes(make_span(kArray));
- EXPECT_EQ(reinterpret_cast<const uint8_t*>(kArray), bytes_span.data());
- EXPECT_EQ(sizeof(kArray), bytes_span.size());
- EXPECT_EQ(bytes_span.size(), bytes_span.size_bytes());
- }
-
- {
- std::vector<int> vec = {1, 1, 2, 3, 5, 8};
- span<int> mutable_span(vec);
- span<const uint8_t> bytes_span = as_bytes(mutable_span);
- EXPECT_EQ(reinterpret_cast<const uint8_t*>(vec.data()), bytes_span.data());
- EXPECT_EQ(sizeof(int) * vec.size(), bytes_span.size());
- EXPECT_EQ(bytes_span.size(), bytes_span.size_bytes());
- }
-}
-
-TEST(SpanTest, AsWritableBytes) {
- std::vector<int> vec = {1, 1, 2, 3, 5, 8};
- span<int> mutable_span(vec);
- span<uint8_t> writable_bytes_span = as_writable_bytes(mutable_span);
- EXPECT_EQ(reinterpret_cast<uint8_t*>(vec.data()), writable_bytes_span.data());
- EXPECT_EQ(sizeof(int) * vec.size(), writable_bytes_span.size());
- EXPECT_EQ(writable_bytes_span.size(), writable_bytes_span.size_bytes());
-
- // Set the first entry of vec to zero while writing through the span.
- std::fill(writable_bytes_span.data(),
- writable_bytes_span.data() + sizeof(int), 0);
- EXPECT_EQ(0, vec[0]);
-}
-
-TEST(SpanTest, MakeSpanFromDataAndSize) {
- int* nullint = nullptr;
- auto empty_span = make_span(nullint, 0);
- EXPECT_TRUE(empty_span.empty());
- EXPECT_EQ(nullptr, empty_span.data());
-
- std::vector<int> vector = {1, 1, 2, 3, 5, 8};
- span<int> span(vector.data(), vector.size());
- auto made_span = make_span(vector.data(), vector.size());
- EXPECT_EQ(span, made_span);
- static_assert(decltype(made_span)::extent == dynamic_extent, "");
-}
-
-TEST(SpanTest, MakeSpanFromPointerPair) {
- int* nullint = nullptr;
- auto empty_span = make_span(nullint, nullint);
- EXPECT_TRUE(empty_span.empty());
- EXPECT_EQ(nullptr, empty_span.data());
-
- std::vector<int> vector = {1, 1, 2, 3, 5, 8};
- span<int> span(vector.data(), vector.size());
- auto made_span = make_span(vector.data(), vector.data() + vector.size());
- EXPECT_EQ(span, made_span);
- static_assert(decltype(made_span)::extent == dynamic_extent, "");
-}
-
-TEST(SpanTest, MakeSpanFromConstexprArray) {
- static constexpr int kArray[] = {1, 2, 3, 4, 5};
- constexpr span<const int> span(kArray);
- EXPECT_EQ(span, make_span(kArray));
- static_assert(decltype(make_span(kArray))::extent == 5, "");
-}
-
-TEST(SpanTest, MakeSpanFromStdArray) {
- const std::array<int, 5> kArray = {{1, 2, 3, 4, 5}};
- span<const int> span(kArray);
- EXPECT_EQ(span, make_span(kArray));
- static_assert(decltype(make_span(kArray))::extent == 5, "");
-}
-
-TEST(SpanTest, MakeSpanFromConstContainer) {
- const std::vector<int> vector = {-1, -2, -3, -4, -5};
- span<const int> span(vector);
- EXPECT_EQ(span, make_span(vector));
- static_assert(decltype(make_span(vector))::extent == dynamic_extent, "");
-}
-
-TEST(SpanTest, MakeSpanFromContainer) {
- std::vector<int> vector = {-1, -2, -3, -4, -5};
- span<int> span(vector);
- EXPECT_EQ(span, make_span(vector));
- static_assert(decltype(make_span(vector))::extent == dynamic_extent, "");
-}
-
-TEST(SpanTest, MakeSpanFromDynamicSpan) {
- static constexpr int kArray[] = {1, 2, 3, 4, 5};
- constexpr span<const int> span(kArray);
- static_assert(std::is_same<decltype(span)::element_type,
- decltype(make_span(span))::element_type>::value,
- "make_span(span) should have the same element_type as span");
-
- static_assert(span.data() == make_span(span).data(),
- "make_span(span) should have the same data() as span");
-
- static_assert(span.size() == make_span(span).size(),
- "make_span(span) should have the same size() as span");
-
- static_assert(decltype(make_span(span))::extent == decltype(span)::extent,
- "make_span(span) should have the same extent as span");
-}
-
-TEST(SpanTest, MakeSpanFromStaticSpan) {
- static constexpr int kArray[] = {1, 2, 3, 4, 5};
- constexpr span<const int, 5> span(kArray);
- static_assert(std::is_same<decltype(span)::element_type,
- decltype(make_span(span))::element_type>::value,
- "make_span(span) should have the same element_type as span");
-
- static_assert(span.data() == make_span(span).data(),
- "make_span(span) should have the same data() as span");
-
- static_assert(span.size() == make_span(span).size(),
- "make_span(span) should have the same size() as span");
-
- static_assert(decltype(make_span(span))::extent == decltype(span)::extent,
- "make_span(span) should have the same extent as span");
-}
-
-TEST(SpanTest, EnsureConstexprGoodness) {
- static constexpr int kArray[] = {5, 4, 3, 2, 1};
- constexpr span<const int> constexpr_span(kArray);
- const size_t size = 2;
-
- const size_t start = 1;
- constexpr span<const int> subspan =
- constexpr_span.subspan(start, start + size);
- for (size_t i = 0; i < subspan.size(); ++i)
- EXPECT_EQ(kArray[start + i], subspan[i]);
-
- constexpr span<const int> firsts = constexpr_span.first(size);
- for (size_t i = 0; i < firsts.size(); ++i)
- EXPECT_EQ(kArray[i], firsts[i]);
-
- constexpr span<const int> lasts = constexpr_span.last(size);
- for (size_t i = 0; i < lasts.size(); ++i) {
- const size_t j = (arraysize(kArray) - size) + i;
- EXPECT_EQ(kArray[j], lasts[i]);
- }
-
- constexpr int item = constexpr_span[size];
- EXPECT_EQ(kArray[size], item);
-}
-
-} // namespace base
diff --git a/base/containers/span_unittest.nc b/base/containers/span_unittest.nc
deleted file mode 100644
index 0d2af89..0000000
--- a/base/containers/span_unittest.nc
+++ /dev/null
@@ -1,167 +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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/containers/span.h"
-
-#include <array>
-#include <set>
-#include <vector>
-
-namespace base {
-
-class Base {
-};
-
-class Derived : Base {
-};
-
-#if defined(NCTEST_DEFAULT_SPAN_WITH_NON_ZERO_STATIC_EXTENT_DISALLOWED) // [r"fatal error: static_assert failed \"Invalid Extent\""]
-
-// A default constructed span must have an extent of 0 or dynamic_extent.
-void WontCompile() {
- span<int, 1> span;
-}
-
-#elif defined(NCTEST_SPAN_FROM_ARRAY_WITH_NON_MATCHING_STATIC_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 1>'"]
-
-// A span with static extent constructed from an array must match the size of
-// the array.
-void WontCompile() {
- int array[] = {1, 2, 3};
- span<int, 1> span(array);
-}
-
-#elif defined(NCTEST_SPAN_FROM_STD_ARRAY_WITH_NON_MATCHING_STATIC_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 2>'"]
-
-// A span with static extent constructed from std::array must match the size of
-// the array.
-void WontCompile() {
- std::array<int, 3> array = {1, 2, 3};
- span<int, 2> span(array);
-}
-
-#elif defined(NCTEST_SPAN_FROM_CONST_STD_ARRAY_WITH_NON_MATCHING_STATIC_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<const int, 2>'"]
-
-// A span with static extent constructed from std::array must match the size of
-// the array.
-void WontCompile() {
- const std::array<int, 3> array = {1, 2, 3};
- span<const int, 2> span(array);
-}
-
-#elif defined(NCTEST_SPAN_FROM_OTHER_SPAN_WITH_MISMATCHING_EXTENT_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 4>'"]
-
-// A span with static extent constructed from another span must match the
-// extent.
-void WontCompile() {
- std::array<int, 3> array = {1, 2, 3};
- span<int, 3> span3(array);
- span<int, 4> span4(span3);
-}
-
-#elif defined(NCTEST_DYNAMIC_SPAN_TO_STATIC_SPAN_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int, 3>'"]
-
-// Converting a dynamic span to a static span should not be allowed.
-void WontCompile() {
- span<int> dynamic_span;
- span<int, 3> static_span(dynamic_span);
-}
-
-#elif defined(NCTEST_DERIVED_TO_BASE_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<base::Base \*>'"]
-
-// Internally, this is represented as a pointer to pointers to Derived. An
-// implicit conversion to a pointer to pointers to Base must not be allowed.
-// If it were allowed, then something like this would be possible.
-// Cat** cats = GetCats();
-// Animals** animals = cats;
-// animals[0] = new Dog(); // Uhoh!
-void WontCompile() {
- span<Derived*> derived_span;
- span<Base*> base_span(derived_span);
-}
-
-#elif defined(NCTEST_PTR_TO_CONSTPTR_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<const int \*>'"]
-
-// Similarly, converting a span<int*> to span<const int*> requires internally
-// converting T** to const T**. This is also disallowed, as it would allow code
-// to violate the contract of const.
-void WontCompile() {
- span<int*> non_const_span;
- span<const int*> const_span(non_const_span);
-}
-
-#elif defined(NCTEST_CONST_CONTAINER_TO_MUTABLE_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int>'"]
-
-// A const container should not be convertible to a mutable span.
-void WontCompile() {
- const std::vector<int> v = {1, 2, 3};
- span<int> span(v);
-}
-
-#elif defined(NCTEST_STD_SET_CONVERSION_DISALLOWED) // [r"fatal error: no matching constructor for initialization of 'span<int>'"]
-
-// A std::set() should not satisfy the requirements for conversion to a span.
-void WontCompile() {
- std::set<int> set;
- span<int> span(set);
-}
-
-#elif defined(NCTEST_STATIC_FRONT_WITH_EXCEEDING_COUNT_DISALLOWED) // [r"fatal error: static_assert failed \"Count must not exceed Extent\""]
-
-// Static first called on a span with static extent must not exceed the size.
-void WontCompile() {
- std::array<int, 3> array = {1, 2, 3};
- span<int, 3> span(array);
- auto first = span.first<4>();
-}
-
-#elif defined(NCTEST_STATIC_LAST_WITH_EXCEEDING_COUNT_DISALLOWED) // [r"fatal error: static_assert failed \"Count must not exceed Extent\""]
-
-// Static last called on a span with static extent must not exceed the size.
-void WontCompile() {
- std::array<int, 3> array = {1, 2, 3};
- span<int, 3> span(array);
- auto last = span.last<4>();
-}
-
-#elif defined(NCTEST_STATIC_SUBSPAN_WITH_EXCEEDING_OFFSET_DISALLOWED) // [r"fatal error: static_assert failed \"Offset must not exceed Extent\""]
-
-// Static subspan called on a span with static extent must not exceed the size.
-void WontCompile() {
- std::array<int, 3> array = {1, 2, 3};
- span<int, 3> span(array);
- auto subspan = span.subspan<4>();
-}
-
-#elif defined(NCTEST_STATIC_SUBSPAN_WITH_EXCEEDING_COUNT_DISALLOWED) // [r"fatal error: static_assert failed \"Count must not exceed Extent - Offset\""]
-
-// Static subspan called on a span with static extent must not exceed the size.
-void WontCompile() {
- std::array<int, 3> array = {1, 2, 3};
- span<int, 3> span(array);
- auto subspan = span.subspan<0, 4>();
-}
-
-#elif defined(NCTEST_AS_WRITABLE_BYTES_WITH_CONST_CONTAINER_DISALLOWED) // [r"fatal error: no matching function for call to 'as_writable_bytes'"]
-
-// as_writable_bytes should not be possible for a const container.
-void WontCompile() {
- const std::vector<int> v = {1, 2, 3};
- span<uint8_t> bytes = as_writable_bytes(make_span(v));
-}
-
-#elif defined(NCTEST_MAKE_SPAN_FROM_SET_CONVERSION_DISALLOWED) // [r"fatal error: no matching function for call to 'make_span'"]
-
-// A std::set() should not satisfy the requirements for conversion to a span.
-void WontCompile() {
- std::set<int> set;
- auto span = make_span(set);
-}
-
-#endif
-
-} // namespace base
diff --git a/base/containers/stack_container_unittest.cc b/base/containers/stack_container_unittest.cc
deleted file mode 100644
index 8c039ad..0000000
--- 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_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_unittest.cc b/base/containers/unique_ptr_adapters_unittest.cc
deleted file mode 100644
index 5b8f1fc..0000000
--- 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/containers/vector_buffer_unittest.cc b/base/containers/vector_buffer_unittest.cc
deleted file mode 100644
index 6d49505..0000000
--- a/base/containers/vector_buffer_unittest.cc
+++ /dev/null
@@ -1,89 +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/vector_buffer.h"
-
-#include "base/test/copy_only_int.h"
-#include "base/test/move_only_int.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-TEST(VectorBuffer, DeletePOD) {
- constexpr int size = 10;
- VectorBuffer<int> buffer(size);
- for (int i = 0; i < size; i++)
- buffer.begin()[i] = i + 1;
-
- buffer.DestructRange(buffer.begin(), buffer.end());
-
- // Delete should do nothing.
- for (int i = 0; i < size; i++)
- EXPECT_EQ(i + 1, buffer.begin()[i]);
-}
-
-TEST(VectorBuffer, DeleteMoveOnly) {
- constexpr int size = 10;
- VectorBuffer<MoveOnlyInt> buffer(size);
- for (int i = 0; i < size; i++)
- new (buffer.begin() + i) MoveOnlyInt(i + 1);
-
- buffer.DestructRange(buffer.begin(), buffer.end());
-
- // Delete should have reset all of the values to 0.
- for (int i = 0; i < size; i++)
- EXPECT_EQ(0, buffer.begin()[i].data());
-}
-
-TEST(VectorBuffer, PODMove) {
- constexpr int size = 10;
- VectorBuffer<int> dest(size);
-
- VectorBuffer<int> original(size);
- for (int i = 0; i < size; i++)
- original.begin()[i] = i + 1;
-
- original.MoveRange(original.begin(), original.end(), dest.begin());
- for (int i = 0; i < size; i++)
- EXPECT_EQ(i + 1, dest.begin()[i]);
-}
-
-TEST(VectorBuffer, MovableMove) {
- constexpr int size = 10;
- VectorBuffer<MoveOnlyInt> dest(size);
-
- VectorBuffer<MoveOnlyInt> original(size);
- for (int i = 0; i < size; i++)
- new (original.begin() + i) MoveOnlyInt(i + 1);
-
- original.MoveRange(original.begin(), original.end(), dest.begin());
-
- // Moving from a MoveOnlyInt resets to 0.
- for (int i = 0; i < size; i++) {
- EXPECT_EQ(0, original.begin()[i].data());
- EXPECT_EQ(i + 1, dest.begin()[i].data());
- }
-}
-
-TEST(VectorBuffer, CopyToMove) {
- constexpr int size = 10;
- VectorBuffer<CopyOnlyInt> dest(size);
-
- VectorBuffer<CopyOnlyInt> original(size);
- for (int i = 0; i < size; i++)
- new (original.begin() + i) CopyOnlyInt(i + 1);
-
- original.MoveRange(original.begin(), original.end(), dest.begin());
-
- // The original should have been destructed, which should reset the value to
- // 0. Technically this dereferences the destructed object.
- for (int i = 0; i < size; i++) {
- EXPECT_EQ(0, original.begin()[i].data());
- EXPECT_EQ(i + 1, dest.begin()[i].data());
- }
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/cpu_unittest.cc b/base/cpu_unittest.cc
deleted file mode 100644
index bfdb1cd..0000000
--- a/base/cpu_unittest.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 "base/cpu.h"
-#include "base/stl_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if _MSC_VER >= 1700
-// C4752: found Intel(R) Advanced Vector Extensions; consider using /arch:AVX.
-#pragma warning(disable: 4752)
-#endif
-
-// Tests whether we can run extended instructions represented by the CPU
-// information. This test actually executes some extended instructions (such as
-// MMX, SSE, etc.) supported by the CPU and sees we can run them without
-// "undefined instruction" exceptions. That is, this test succeeds when this
-// test finishes without a crash.
-TEST(CPU, RunExtendedInstructions) {
-#if defined(ARCH_CPU_X86_FAMILY)
- // Retrieve the CPU information.
- base::CPU cpu;
-
- ASSERT_TRUE(cpu.has_mmx());
- ASSERT_TRUE(cpu.has_sse());
- ASSERT_TRUE(cpu.has_sse2());
-
-// GCC and clang instruction test.
-#if defined(COMPILER_GCC)
- // Execute an MMX instruction.
- __asm__ __volatile__("emms\n" : : : "mm0");
-
- // Execute an SSE instruction.
- __asm__ __volatile__("xorps %%xmm0, %%xmm0\n" : : : "xmm0");
-
- // Execute an SSE 2 instruction.
- __asm__ __volatile__("psrldq $0, %%xmm0\n" : : : "xmm0");
-
- if (cpu.has_sse3()) {
- // Execute an SSE 3 instruction.
- __asm__ __volatile__("addsubpd %%xmm0, %%xmm0\n" : : : "xmm0");
- }
-
- if (cpu.has_ssse3()) {
- // Execute a Supplimental SSE 3 instruction.
- __asm__ __volatile__("psignb %%xmm0, %%xmm0\n" : : : "xmm0");
- }
-
- if (cpu.has_sse41()) {
- // Execute an SSE 4.1 instruction.
- __asm__ __volatile__("pmuldq %%xmm0, %%xmm0\n" : : : "xmm0");
- }
-
- if (cpu.has_sse42()) {
- // Execute an SSE 4.2 instruction.
- __asm__ __volatile__("crc32 %%eax, %%eax\n" : : : "eax");
- }
-
- if (cpu.has_popcnt()) {
- // Execute a POPCNT instruction.
- __asm__ __volatile__("popcnt %%eax, %%eax\n" : : : "eax");
- }
-
- if (cpu.has_avx()) {
- // Execute an AVX instruction.
- __asm__ __volatile__("vzeroupper\n" : : : "xmm0");
- }
-
- if (cpu.has_avx2()) {
- // Execute an AVX 2 instruction.
- __asm__ __volatile__("vpunpcklbw %%ymm0, %%ymm0, %%ymm0\n" : : : "xmm0");
- }
-
-// Visual C 32 bit and ClangCL 32/64 bit test.
-#elif defined(COMPILER_MSVC) && (defined(ARCH_CPU_32_BITS) || \
- (defined(ARCH_CPU_64_BITS) && defined(__clang__)))
-
- // Execute an MMX instruction.
- __asm emms;
-
- // Execute an SSE instruction.
- __asm xorps xmm0, xmm0;
-
- // Execute an SSE 2 instruction.
- __asm psrldq xmm0, 0;
-
- if (cpu.has_sse3()) {
- // Execute an SSE 3 instruction.
- __asm addsubpd xmm0, xmm0;
- }
-
- if (cpu.has_ssse3()) {
- // Execute a Supplimental SSE 3 instruction.
- __asm psignb xmm0, xmm0;
- }
-
- if (cpu.has_sse41()) {
- // Execute an SSE 4.1 instruction.
- __asm pmuldq xmm0, xmm0;
- }
-
- if (cpu.has_sse42()) {
- // Execute an SSE 4.2 instruction.
- __asm crc32 eax, eax;
- }
-
- if (cpu.has_popcnt()) {
- // Execute a POPCNT instruction.
- __asm popcnt eax, eax;
- }
-
-// Visual C 2012 required for AVX.
-#if _MSC_VER >= 1700
- if (cpu.has_avx()) {
- // Execute an AVX instruction.
- __asm vzeroupper;
- }
-
- if (cpu.has_avx2()) {
- // Execute an AVX 2 instruction.
- __asm vpunpcklbw ymm0, ymm0, ymm0
- }
-#endif // _MSC_VER >= 1700
-#endif // defined(COMPILER_GCC)
-#endif // defined(ARCH_CPU_X86_FAMILY)
-}
-
-// For https://crbug.com/249713
-TEST(CPU, BrandAndVendorContainsNoNUL) {
- base::CPU cpu;
- EXPECT_FALSE(base::ContainsValue(cpu.cpu_brand(), '\0'));
- EXPECT_FALSE(base::ContainsValue(cpu.vendor_name(), '\0'));
-}
diff --git a/base/debug/activity_analyzer_unittest.cc b/base/debug/activity_analyzer_unittest.cc
deleted file mode 100644
index e08b43a..0000000
--- 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/activity_tracker_unittest.cc b/base/debug/activity_tracker_unittest.cc
deleted file mode 100644
index e2b61a9..0000000
--- a/base/debug/activity_tracker_unittest.cc
+++ /dev/null
@@ -1,585 +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_tracker.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.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/rand_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 ActivityTrackerTest : public testing::Test {
- public:
- const int kMemorySize = 1 << 20; // 1MiB
- const int kStackSize = 1 << 10; // 1KiB
-
- using ActivityId = ThreadActivityTracker::ActivityId;
-
- ActivityTrackerTest() = default;
-
- ~ActivityTrackerTest() 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);
- }
-
- size_t GetGlobalActiveTrackerCount() {
- GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
- if (!global_tracker)
- return 0;
- return global_tracker->thread_tracker_count_.load(
- std::memory_order_relaxed);
- }
-
- size_t GetGlobalInactiveTrackerCount() {
- GlobalActivityTracker* global_tracker = GlobalActivityTracker::Get();
- if (!global_tracker)
- return 0;
- AutoLock autolock(global_tracker->thread_tracker_allocator_lock_);
- return global_tracker->thread_tracker_allocator_.cache_used();
- }
-
- size_t GetGlobalUserDataMemoryCacheUsed() {
- return GlobalActivityTracker::Get()->user_data_allocator_.cache_used();
- }
-
- void HandleProcessExit(int64_t id,
- int64_t stamp,
- int code,
- GlobalActivityTracker::ProcessPhase phase,
- std::string&& command,
- ActivityUserData::Snapshot&& data) {
- exit_id_ = id;
- exit_stamp_ = stamp;
- exit_code_ = code;
- exit_phase_ = phase;
- exit_command_ = std::move(command);
- exit_data_ = std::move(data);
- }
-
- int64_t exit_id_ = 0;
- int64_t exit_stamp_;
- int exit_code_;
- GlobalActivityTracker::ProcessPhase exit_phase_;
- std::string exit_command_;
- ActivityUserData::Snapshot exit_data_;
-};
-
-TEST_F(ActivityTrackerTest, UserDataTest) {
- char buffer[256];
- memset(buffer, 0, sizeof(buffer));
- ActivityUserData data(buffer, sizeof(buffer));
- size_t space = sizeof(buffer) - sizeof(ActivityUserData::MemoryHeader);
- ASSERT_EQ(space, data.available_);
-
- data.SetInt("foo", 1);
- space -= 24;
- ASSERT_EQ(space, data.available_);
-
- data.SetUint("b", 1U); // Small names fit beside header in a word.
- space -= 16;
- ASSERT_EQ(space, data.available_);
-
- data.Set("c", buffer, 10);
- space -= 24;
- ASSERT_EQ(space, data.available_);
-
- data.SetString("dear john", "it's been fun");
- space -= 32;
- ASSERT_EQ(space, data.available_);
-
- data.Set("c", buffer, 20);
- ASSERT_EQ(space, data.available_);
-
- data.SetString("dear john", "but we're done together");
- ASSERT_EQ(space, data.available_);
-
- data.SetString("dear john", "bye");
- ASSERT_EQ(space, data.available_);
-
- data.SetChar("d", 'x');
- space -= 8;
- ASSERT_EQ(space, data.available_);
-
- data.SetBool("ee", true);
- space -= 16;
- ASSERT_EQ(space, data.available_);
-
- data.SetString("f", "");
- space -= 8;
- ASSERT_EQ(space, data.available_);
-}
-
-TEST_F(ActivityTrackerTest, PushPopTest) {
- std::unique_ptr<ThreadActivityTracker> tracker = CreateActivityTracker();
- ThreadActivityTracker::Snapshot snapshot;
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(0U, snapshot.activity_stack_depth);
- ASSERT_EQ(0U, snapshot.activity_stack.size());
-
- char origin1;
- ActivityId id1 = tracker->PushActivity(&origin1, Activity::ACT_TASK,
- ActivityData::ForTask(11));
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(1U, snapshot.activity_stack_depth);
- ASSERT_EQ(1U, snapshot.activity_stack.size());
- EXPECT_NE(0, snapshot.activity_stack[0].time_internal);
- EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
- EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1),
- snapshot.activity_stack[0].origin_address);
- EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id);
-
- char origin2;
- char lock2;
- ActivityId id2 = tracker->PushActivity(&origin2, Activity::ACT_LOCK,
- ActivityData::ForLock(&lock2));
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(2U, snapshot.activity_stack_depth);
- ASSERT_EQ(2U, snapshot.activity_stack.size());
- EXPECT_LE(snapshot.activity_stack[0].time_internal,
- snapshot.activity_stack[1].time_internal);
- EXPECT_EQ(Activity::ACT_LOCK, snapshot.activity_stack[1].activity_type);
- EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin2),
- snapshot.activity_stack[1].origin_address);
- EXPECT_EQ(reinterpret_cast<uintptr_t>(&lock2),
- snapshot.activity_stack[1].data.lock.lock_address);
-
- tracker->PopActivity(id2);
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(1U, snapshot.activity_stack_depth);
- ASSERT_EQ(1U, snapshot.activity_stack.size());
- EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
- EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin1),
- snapshot.activity_stack[0].origin_address);
- EXPECT_EQ(11U, snapshot.activity_stack[0].data.task.sequence_id);
-
- tracker->PopActivity(id1);
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(0U, snapshot.activity_stack_depth);
- ASSERT_EQ(0U, snapshot.activity_stack.size());
-}
-
-TEST_F(ActivityTrackerTest, ScopedTaskTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
-
- ThreadActivityTracker* tracker =
- GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
- ThreadActivityTracker::Snapshot snapshot;
- ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed());
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(0U, snapshot.activity_stack_depth);
- ASSERT_EQ(0U, snapshot.activity_stack.size());
-
- {
- PendingTask task1(FROM_HERE, DoNothing());
- ScopedTaskRunActivity activity1(task1);
- ActivityUserData& user_data1 = activity1.user_data();
- (void)user_data1; // Tell compiler it's been used.
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(1U, snapshot.activity_stack_depth);
- ASSERT_EQ(1U, snapshot.activity_stack.size());
- EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
-
- {
- PendingTask task2(FROM_HERE, DoNothing());
- ScopedTaskRunActivity activity2(task2);
- ActivityUserData& user_data2 = activity2.user_data();
- (void)user_data2; // Tell compiler it's been used.
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(2U, snapshot.activity_stack_depth);
- ASSERT_EQ(2U, snapshot.activity_stack.size());
- EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[1].activity_type);
- }
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(1U, snapshot.activity_stack_depth);
- ASSERT_EQ(1U, snapshot.activity_stack.size());
- EXPECT_EQ(Activity::ACT_TASK, snapshot.activity_stack[0].activity_type);
- }
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(0U, snapshot.activity_stack_depth);
- ASSERT_EQ(0U, snapshot.activity_stack.size());
- ASSERT_EQ(2U, GetGlobalUserDataMemoryCacheUsed());
-}
-
-namespace {
-
-class SimpleLockThread : public SimpleThread {
- public:
- SimpleLockThread(const std::string& name, Lock* lock)
- : SimpleThread(name, Options()),
- lock_(lock),
- data_changed_(false),
- is_running_(false) {}
-
- ~SimpleLockThread() override = default;
-
- void Run() override {
- ThreadActivityTracker* tracker =
- GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
- uint32_t pre_version = tracker->GetDataVersionForTesting();
-
- is_running_.store(true, std::memory_order_relaxed);
- lock_->Acquire();
- data_changed_ = tracker->GetDataVersionForTesting() != pre_version;
- lock_->Release();
- is_running_.store(false, std::memory_order_relaxed);
- }
-
- bool IsRunning() { return is_running_.load(std::memory_order_relaxed); }
-
- bool WasDataChanged() { return data_changed_; };
-
- private:
- Lock* lock_;
- bool data_changed_;
- std::atomic<bool> is_running_;
-
- DISALLOW_COPY_AND_ASSIGN(SimpleLockThread);
-};
-
-} // namespace
-
-TEST_F(ActivityTrackerTest, LockTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
-
- ThreadActivityTracker* tracker =
- GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
- ThreadActivityTracker::Snapshot snapshot;
- ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed());
-
- Lock lock;
- uint32_t pre_version = tracker->GetDataVersionForTesting();
-
- // Check no activity when only "trying" a lock.
- EXPECT_TRUE(lock.Try());
- EXPECT_EQ(pre_version, tracker->GetDataVersionForTesting());
- lock.Release();
- EXPECT_EQ(pre_version, tracker->GetDataVersionForTesting());
-
- // Check no activity when acquiring a free lock.
- SimpleLockThread t1("locker1", &lock);
- t1.Start();
- t1.Join();
- EXPECT_FALSE(t1.WasDataChanged());
-
- // Check that activity is recorded when acquring a busy lock.
- SimpleLockThread t2("locker2", &lock);
- lock.Acquire();
- t2.Start();
- while (!t2.IsRunning())
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
- // t2 can't join until the lock is released but have to give time for t2 to
- // actually block on the lock before releasing it or the results will not
- // be correct.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(200));
- lock.Release();
- // Now the results will be valid.
- t2.Join();
- EXPECT_TRUE(t2.WasDataChanged());
-}
-
-TEST_F(ActivityTrackerTest, ExceptionTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- GlobalActivityTracker* global = GlobalActivityTracker::Get();
-
- ThreadActivityTracker* tracker =
- GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
- ThreadActivityTracker::Snapshot snapshot;
- ASSERT_EQ(0U, GetGlobalUserDataMemoryCacheUsed());
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- ASSERT_EQ(0U, snapshot.last_exception.activity_type);
-
- char origin;
- global->RecordException(&origin, 42);
-
- ASSERT_TRUE(tracker->CreateSnapshot(&snapshot));
- EXPECT_EQ(Activity::ACT_EXCEPTION, snapshot.last_exception.activity_type);
- EXPECT_EQ(reinterpret_cast<uintptr_t>(&origin),
- snapshot.last_exception.origin_address);
- EXPECT_EQ(42U, snapshot.last_exception.data.exception.code);
-}
-
-TEST_F(ActivityTrackerTest, CreateWithFileTest) {
- const char temp_name[] = "CreateWithFileTest";
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath temp_file = temp_dir.GetPath().AppendASCII(temp_name);
- const size_t temp_size = 64 << 10; // 64 KiB
-
- // Create a global tracker on a new file.
- ASSERT_FALSE(PathExists(temp_file));
- GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "foo", 3);
- GlobalActivityTracker* global = GlobalActivityTracker::Get();
- EXPECT_EQ(std::string("foo"), global->allocator()->Name());
- global->ReleaseTrackerForCurrentThreadForTesting();
- delete global;
-
- // Create a global tracker over an existing file, replacing it. If the
- // replacement doesn't work, the name will remain as it was first created.
- ASSERT_TRUE(PathExists(temp_file));
- GlobalActivityTracker::CreateWithFile(temp_file, temp_size, 0, "bar", 3);
- global = GlobalActivityTracker::Get();
- EXPECT_EQ(std::string("bar"), global->allocator()->Name());
- global->ReleaseTrackerForCurrentThreadForTesting();
- delete global;
-}
-
-
-// GlobalActivityTracker tests below.
-
-TEST_F(ActivityTrackerTest, BasicTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- GlobalActivityTracker* global = GlobalActivityTracker::Get();
-
- // Ensure the data repositories have backing store, indicated by non-zero ID.
- EXPECT_NE(0U, global->process_data().id());
-}
-
-namespace {
-
-class SimpleActivityThread : public SimpleThread {
- public:
- SimpleActivityThread(const std::string& name,
- const void* origin,
- Activity::Type activity,
- const ActivityData& data)
- : SimpleThread(name, Options()),
- origin_(origin),
- activity_(activity),
- data_(data),
- ready_(false),
- exit_(false),
- exit_condition_(&lock_) {}
-
- ~SimpleActivityThread() override = default;
-
- void Run() override {
- ThreadActivityTracker::ActivityId id =
- GlobalActivityTracker::Get()
- ->GetOrCreateTrackerForCurrentThread()
- ->PushActivity(origin_, 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* origin_;
- 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(ActivityTrackerTest, ThreadDeathTest) {
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- GlobalActivityTracker::Get()->GetOrCreateTrackerForCurrentThread();
- const size_t starting_active = GetGlobalActiveTrackerCount();
- const size_t starting_inactive = GetGlobalInactiveTrackerCount();
-
- SimpleActivityThread t1("t1", nullptr, Activity::ACT_TASK,
- ActivityData::ForTask(11));
- t1.Start();
- t1.WaitReady();
- EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount());
- EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
-
- t1.Exit();
- t1.Join();
- EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
- EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
-
- // Start another thread and ensure it re-uses the existing memory.
-
- SimpleActivityThread t2("t2", nullptr, Activity::ACT_TASK,
- ActivityData::ForTask(22));
- t2.Start();
- t2.WaitReady();
- EXPECT_EQ(starting_active + 1, GetGlobalActiveTrackerCount());
- EXPECT_EQ(starting_inactive, GetGlobalInactiveTrackerCount());
-
- t2.Exit();
- t2.Join();
- EXPECT_EQ(starting_active, GetGlobalActiveTrackerCount());
- EXPECT_EQ(starting_inactive + 1, GetGlobalInactiveTrackerCount());
-}
-
-TEST_F(ActivityTrackerTest, ProcessDeathTest) {
- // This doesn't actually create and destroy a process. Instead, it uses for-
- // testing interfaces to simulate data created by other processes.
- const int64_t other_process_id = GetCurrentProcId() + 1;
-
- GlobalActivityTracker::CreateWithLocalMemory(kMemorySize, 0, "", 3, 0);
- GlobalActivityTracker* global = GlobalActivityTracker::Get();
- ThreadActivityTracker* thread = global->GetOrCreateTrackerForCurrentThread();
-
- // Get callbacks for process exit.
- global->SetProcessExitCallback(
- Bind(&ActivityTrackerTest::HandleProcessExit, Unretained(this)));
-
- // Pretend than another process has started.
- global->RecordProcessLaunch(other_process_id, FILE_PATH_LITERAL("foo --bar"));
-
- // Do some activities.
- PendingTask task(FROM_HERE, DoNothing());
- ScopedTaskRunActivity activity(task);
- ActivityUserData& user_data = activity.user_data();
- ASSERT_NE(0U, user_data.id());
-
- // Get the memory-allocator references to that data.
- PersistentMemoryAllocator::Reference proc_data_ref =
- global->allocator()->GetAsReference(
- global->process_data().GetBaseAddress(),
- GlobalActivityTracker::kTypeIdProcessDataRecord);
- ASSERT_TRUE(proc_data_ref);
- PersistentMemoryAllocator::Reference tracker_ref =
- global->allocator()->GetAsReference(
- thread->GetBaseAddress(),
- GlobalActivityTracker::kTypeIdActivityTracker);
- ASSERT_TRUE(tracker_ref);
- PersistentMemoryAllocator::Reference user_data_ref =
- global->allocator()->GetAsReference(
- user_data.GetBaseAddress(),
- GlobalActivityTracker::kTypeIdUserDataRecord);
- ASSERT_TRUE(user_data_ref);
-
- // Make a copy of the thread-tracker state so it can be restored later.
- const size_t tracker_size = global->allocator()->GetAllocSize(tracker_ref);
- std::unique_ptr<char[]> tracker_copy(new char[tracker_size]);
- memcpy(tracker_copy.get(), thread->GetBaseAddress(), tracker_size);
-
- // Change the objects to appear to be owned by another process. Use a "past"
- // time so that exit-time is always later than create-time.
- const int64_t past_stamp = Time::Now().ToInternalValue() - 1;
- int64_t owning_id;
- int64_t stamp;
- ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
- global->process_data().GetBaseAddress(), &owning_id, &stamp));
- EXPECT_NE(other_process_id, owning_id);
- ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
- thread->GetBaseAddress(), &owning_id, &stamp));
- EXPECT_NE(other_process_id, owning_id);
- ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
- &owning_id, &stamp));
- EXPECT_NE(other_process_id, owning_id);
- global->process_data().SetOwningProcessIdForTesting(other_process_id,
- past_stamp);
- thread->SetOwningProcessIdForTesting(other_process_id, past_stamp);
- user_data.SetOwningProcessIdForTesting(other_process_id, past_stamp);
- ASSERT_TRUE(ActivityUserData::GetOwningProcessId(
- global->process_data().GetBaseAddress(), &owning_id, &stamp));
- EXPECT_EQ(other_process_id, owning_id);
- ASSERT_TRUE(ThreadActivityTracker::GetOwningProcessId(
- thread->GetBaseAddress(), &owning_id, &stamp));
- EXPECT_EQ(other_process_id, owning_id);
- ASSERT_TRUE(ActivityUserData::GetOwningProcessId(user_data.GetBaseAddress(),
- &owning_id, &stamp));
- EXPECT_EQ(other_process_id, owning_id);
-
- // Check that process exit will perform callback and free the allocations.
- ASSERT_EQ(0, exit_id_);
- ASSERT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecord,
- global->allocator()->GetType(proc_data_ref));
- ASSERT_EQ(GlobalActivityTracker::kTypeIdActivityTracker,
- global->allocator()->GetType(tracker_ref));
- ASSERT_EQ(GlobalActivityTracker::kTypeIdUserDataRecord,
- global->allocator()->GetType(user_data_ref));
- global->RecordProcessExit(other_process_id, 0);
- EXPECT_EQ(other_process_id, exit_id_);
- EXPECT_EQ("foo --bar", exit_command_);
- EXPECT_EQ(GlobalActivityTracker::kTypeIdProcessDataRecordFree,
- global->allocator()->GetType(proc_data_ref));
- EXPECT_EQ(GlobalActivityTracker::kTypeIdActivityTrackerFree,
- global->allocator()->GetType(tracker_ref));
- EXPECT_EQ(GlobalActivityTracker::kTypeIdUserDataRecordFree,
- global->allocator()->GetType(user_data_ref));
-
- // Restore memory contents and types so things don't crash when doing real
- // process clean-up.
- memcpy(const_cast<void*>(thread->GetBaseAddress()), tracker_copy.get(),
- tracker_size);
- global->allocator()->ChangeType(
- proc_data_ref, GlobalActivityTracker::kTypeIdProcessDataRecord,
- GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
- global->allocator()->ChangeType(
- tracker_ref, GlobalActivityTracker::kTypeIdActivityTracker,
- GlobalActivityTracker::kTypeIdActivityTrackerFree, false);
- global->allocator()->ChangeType(
- user_data_ref, GlobalActivityTracker::kTypeIdUserDataRecord,
- GlobalActivityTracker::kTypeIdUserDataRecordFree, false);
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/alias_unittest.cc b/base/debug/alias_unittest.cc
deleted file mode 100644
index 66682f1..0000000
--- a/base/debug/alias_unittest.cc
+++ /dev/null
@@ -1,28 +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 <memory>
-#include <string>
-
-#include "base/debug/alias.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(DebugAlias, Test) {
- std::unique_ptr<std::string> input =
- std::make_unique<std::string>("string contents");
-
- // Verify the contents get copied + the new local variable has the right type.
- DEBUG_ALIAS_FOR_CSTR(copy1, input->c_str(), 100 /* > input->size() */);
- static_assert(sizeof(copy1) == 100,
- "Verification that copy1 has expected size");
- EXPECT_STREQ("string contents", copy1);
-
- // Verify that the copy is properly null-terminated even when it is smaller
- // than the input string.
- DEBUG_ALIAS_FOR_CSTR(copy2, input->c_str(), 3 /* < input->size() */);
- static_assert(sizeof(copy2) == 3,
- "Verification that copy2 has expected size");
- EXPECT_STREQ("st", copy2);
- EXPECT_EQ('\0', copy2[2]);
-}
diff --git a/base/debug/crash_logging_unittest.cc b/base/debug/crash_logging_unittest.cc
deleted file mode 100644
index c10d36e..0000000
--- 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/debugger_unittest.cc b/base/debug/debugger_unittest.cc
deleted file mode 100644
index 23ea83d..0000000
--- a/base/debug/debugger_unittest.cc
+++ /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.
-
-#include "base/debug/debugger.h"
-
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-void CrashWithBreakDebugger() {
- base::debug::SetSuppressDebugUI(false);
- base::debug::BreakDebugger();
-
-#if defined(OS_WIN)
- // This should not be executed.
- _exit(125);
-#endif
-}
-#endif // defined(GTEST_HAS_DEATH_TEST)
-
-} // namespace
-
-// Death tests misbehave on Android.
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-
-TEST(Debugger, CrashAtBreakpoint) {
- EXPECT_DEATH(CrashWithBreakDebugger(), "");
-}
-
-#if defined(OS_WIN)
-TEST(Debugger, DoesntExecuteBeyondBreakpoint) {
- EXPECT_EXIT(CrashWithBreakDebugger(),
- ::testing::ExitedWithCode(0x80000003), "");
-}
-#endif // defined(OS_WIN)
-
-#else // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-TEST(Debugger, NoTest) {
-}
-#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
diff --git a/base/debug/elf_reader_linux_unittest.cc b/base/debug/elf_reader_linux_unittest.cc
deleted file mode 100644
index 88ed502..0000000
--- a/base/debug/elf_reader_linux_unittest.cc
+++ /dev/null
@@ -1,70 +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/debug/elf_reader_linux.h"
-
-#include <dlfcn.h>
-
-#include "base/files/memory_mapped_file.h"
-#include "base/strings/string_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-extern char __executable_start;
-
-namespace base {
-namespace debug {
-
-// The linker flag --build-id is passed only on official builds. Clang does not
-// enable it by default and we do not have build id section in non-official
-// builds.
-#if defined(OFFICIAL_BUILD)
-TEST(ElfReaderTest, ReadElfBuildId) {
- Optional<std::string> build_id = ReadElfBuildId(&__executable_start);
- ASSERT_TRUE(build_id);
- const size_t kGuidBytes = 20;
- EXPECT_EQ(2 * kGuidBytes, build_id.value().size());
- for (char c : *build_id) {
- EXPECT_TRUE(IsHexDigit(c));
- EXPECT_FALSE(IsAsciiLower(c));
- }
-}
-#endif
-
-TEST(ElfReaderTest, ReadElfLibraryName) {
-#if defined(OS_ANDROID)
- // On Android the library loader memory maps the full so file.
- const char kLibraryName[] = "lib_base_unittests__library";
- const void* addr = &__executable_start;
-#else
- // On Linux the executable does not contain soname and is not mapped till
- // dynamic segment. So, use malloc wrapper so file on which the test already
- // depends on.
- const char kLibraryName[] = MALLOC_WRAPPER_LIB;
- // Find any symbol in the loaded file.
- void* handle = dlopen(kLibraryName, RTLD_NOW | RTLD_LOCAL);
- const void* init_addr = dlsym(handle, "_init");
- // Use this symbol to get full path to the loaded library.
- Dl_info info;
- int res = dladdr(init_addr, &info);
- ASSERT_NE(0, res);
- std::string filename(info.dli_fname);
- EXPECT_FALSE(filename.empty());
- EXPECT_NE(std::string::npos, filename.find(kLibraryName));
-
- // Memory map the so file and use it to test reading so name.
- MemoryMappedFile file;
- file.Initialize(FilePath(filename));
- const void* addr = file.data();
-#endif
-
- auto name = ReadElfLibraryName(addr);
- ASSERT_TRUE(name);
- EXPECT_NE(std::string::npos, name->find(kLibraryName))
- << "Library name " << *name << " doesn't contain expected "
- << kLibraryName;
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/leak_tracker_unittest.cc b/base/debug/leak_tracker_unittest.cc
deleted file mode 100644
index b9ecdcf..0000000
--- a/base/debug/leak_tracker_unittest.cc
+++ /dev/null
@@ -1,115 +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/debug/leak_tracker.h"
-
-#include <memory>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace debug {
-
-namespace {
-
-class ClassA {
- private:
- LeakTracker<ClassA> leak_tracker_;
-};
-
-class ClassB {
- private:
- LeakTracker<ClassB> leak_tracker_;
-};
-
-#ifndef ENABLE_LEAK_TRACKER
-
-// If leak tracking is disabled, we should do nothing.
-TEST(LeakTrackerTest, NotEnabled) {
- EXPECT_EQ(-1, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(-1, LeakTracker<ClassB>::NumLiveInstances());
-
- // Use unique_ptr so compiler doesn't complain about unused variables.
- std::unique_ptr<ClassA> a1(new ClassA);
- std::unique_ptr<ClassB> b1(new ClassB);
- std::unique_ptr<ClassB> b2(new ClassB);
-
- EXPECT_EQ(-1, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(-1, LeakTracker<ClassB>::NumLiveInstances());
-}
-
-#else
-
-TEST(LeakTrackerTest, Basic) {
- {
- ClassA a1;
-
- EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances());
-
- ClassB b1;
- ClassB b2;
-
- EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances());
-
- std::unique_ptr<ClassA> a2(new ClassA);
-
- EXPECT_EQ(2, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances());
-
- a2.reset();
-
- EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(2, LeakTracker<ClassB>::NumLiveInstances());
- }
-
- EXPECT_EQ(0, LeakTracker<ClassA>::NumLiveInstances());
- EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances());
-}
-
-// Try some orderings of create/remove to hit different cases in the linked-list
-// assembly.
-TEST(LeakTrackerTest, LinkedList) {
- EXPECT_EQ(0, LeakTracker<ClassB>::NumLiveInstances());
-
- std::unique_ptr<ClassA> a1(new ClassA);
- std::unique_ptr<ClassA> a2(new ClassA);
- std::unique_ptr<ClassA> a3(new ClassA);
- std::unique_ptr<ClassA> a4(new ClassA);
-
- EXPECT_EQ(4, LeakTracker<ClassA>::NumLiveInstances());
-
- // Remove the head of the list (a1).
- a1.reset();
- EXPECT_EQ(3, LeakTracker<ClassA>::NumLiveInstances());
-
- // Remove the tail of the list (a4).
- a4.reset();
- EXPECT_EQ(2, LeakTracker<ClassA>::NumLiveInstances());
-
- // Append to the new tail of the list (a3).
- std::unique_ptr<ClassA> a5(new ClassA);
- EXPECT_EQ(3, LeakTracker<ClassA>::NumLiveInstances());
-
- a2.reset();
- a3.reset();
-
- EXPECT_EQ(1, LeakTracker<ClassA>::NumLiveInstances());
-
- a5.reset();
- EXPECT_EQ(0, LeakTracker<ClassA>::NumLiveInstances());
-}
-
-TEST(LeakTrackerTest, NoOpCheckForLeaks) {
- // There are no live instances of ClassA, so this should do nothing.
- LeakTracker<ClassA>::CheckForLeaks();
-}
-
-#endif // ENABLE_LEAK_TRACKER
-
-} // namespace
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/proc_maps_linux_unittest.cc b/base/debug/proc_maps_linux_unittest.cc
deleted file mode 100644
index d291507..0000000
--- 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_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace debug {
-
-TEST(ProcMapsTest, Empty) {
- std::vector<MappedMemoryRegion> regions;
- EXPECT_TRUE(ParseProcMaps("", ®ions));
- 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, ®ions));
- 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, ®ions));
- 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, ®ions));
-}
-
-TEST(ProcMapsTest, NoPath) {
- static const char kNoPath[] =
- "00400000-0040b000 rw-p 00000000 00:00 0 \n";
-
- std::vector<MappedMemoryRegion> regions;
- ASSERT_TRUE(ParseProcMaps(kNoPath, ®ions));
- 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, ®ions));
- 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, ®ions));
- 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, ®ions));
- 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, ®ions));
- 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, ®ions));
- 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> ®ions) {
- // 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, ®ions));
- 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], ®ions));
- }
-}
-
-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], ®ions));
- }
-}
-
-TEST(ProcMapsTest, ParseProcMapsEmptyString) {
- std::vector<MappedMemoryRegion> regions;
- EXPECT_TRUE(ParseProcMaps("", ®ions));
- 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, ®ions));
- 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 6d37c40..0000000
--- a/base/debug/stack_trace_unittest.cc
+++ /dev/null
@@ -1,258 +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/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_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) && !defined(OS_FUCHSIA)
-#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) && !defined(OS_FUCHSIA)
-
-} // namespace debug
-} // namespace base
diff --git a/base/debug/task_annotator_unittest.cc b/base/debug/task_annotator_unittest.cc
deleted file mode 100644
index 51a5d32..0000000
--- a/base/debug/task_annotator_unittest.cc
+++ /dev/null
@@ -1,371 +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/task_annotator.h"
-
-#include <algorithm>
-#include <vector>
-
-#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/pending_task.h"
-#include "base/run_loop.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace debug {
-namespace {
-
-void TestTask(int* result) {
- *result = 123;
-}
-
-} // namespace
-
-TEST(TaskAnnotatorTest, QueueAndRunTask) {
- int result = 0;
- PendingTask pending_task(FROM_HERE, BindOnce(&TestTask, &result));
-
- TaskAnnotator annotator;
- annotator.DidQueueTask("TaskAnnotatorTest::Queue", pending_task);
- EXPECT_EQ(0, result);
- annotator.RunTask("TaskAnnotatorTest::Queue", &pending_task);
- EXPECT_EQ(123, result);
-}
-
-// Test task annotator integration in base APIs and ensuing support for
-// backtraces. Tasks posted across multiple threads in this test fixture should
-// be synchronized as BeforeRunTask() and VerifyTraceAndPost() assume tasks are
-// observed in lock steps, one at a time.
-class TaskAnnotatorBacktraceIntegrationTest
- : public ::testing::Test,
- public TaskAnnotator::ObserverForTesting {
- public:
- using ExpectedTrace = std::vector<const void*>;
-
- TaskAnnotatorBacktraceIntegrationTest() = default;
-
- ~TaskAnnotatorBacktraceIntegrationTest() override = default;
-
- // TaskAnnotator::ObserverForTesting:
- void BeforeRunTask(const PendingTask* pending_task) override {
- AutoLock auto_lock(on_before_run_task_lock_);
- last_posted_from_ = pending_task->posted_from;
- last_task_backtrace_ = pending_task->task_backtrace;
- }
-
- void SetUp() override { TaskAnnotator::RegisterObserverForTesting(this); }
-
- void TearDown() override { TaskAnnotator::ClearObserverForTesting(); }
-
- void VerifyTraceAndPost(const scoped_refptr<SequencedTaskRunner>& task_runner,
- const Location& posted_from,
- const Location& next_from_here,
- const ExpectedTrace& expected_trace,
- OnceClosure task) {
- SCOPED_TRACE(StringPrintf("Callback Depth: %zu", expected_trace.size()));
-
- EXPECT_EQ(posted_from, last_posted_from_);
- for (size_t i = 0; i < last_task_backtrace_.size(); i++) {
- SCOPED_TRACE(StringPrintf("Trace frame: %zu", i));
- if (i < expected_trace.size())
- EXPECT_EQ(expected_trace[i], last_task_backtrace_[i]);
- else
- EXPECT_EQ(nullptr, last_task_backtrace_[i]);
- }
-
- task_runner->PostTask(next_from_here, std::move(task));
- }
-
- // Same as VerifyTraceAndPost() with the exception that it also posts a task
- // that will prevent |task| from running until |wait_before_next_task| is
- // signaled.
- void VerifyTraceAndPostWithBlocker(
- const scoped_refptr<SequencedTaskRunner>& task_runner,
- const Location& posted_from,
- const Location& next_from_here,
- const ExpectedTrace& expected_trace,
- OnceClosure task,
- WaitableEvent* wait_before_next_task) {
- DCHECK(wait_before_next_task);
-
- // Need to lock to ensure the upcoming VerifyTraceAndPost() runs before the
- // BeforeRunTask() hook for the posted WaitableEvent::Wait(). Otherwise the
- // upcoming VerifyTraceAndPost() will race to read the state saved in the
- // BeforeRunTask() hook preceding the current task.
- AutoLock auto_lock(on_before_run_task_lock_);
- task_runner->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEvent::Wait, Unretained(wait_before_next_task)));
- VerifyTraceAndPost(task_runner, posted_from, next_from_here, expected_trace,
- std::move(task));
- }
-
- protected:
- static void RunTwo(OnceClosure c1, OnceClosure c2) {
- std::move(c1).Run();
- std::move(c2).Run();
- }
-
- private:
- // While calls to VerifyTraceAndPost() are strictly ordered in tests below
- // (and hence non-racy), some helper methods (e.g. Wait/Signal) do racily call
- // into BeforeRunTask(). This Lock ensures these unobserved writes are not
- // racing. Locking isn't required on read per the VerifyTraceAndPost()
- // themselves being ordered.
- Lock on_before_run_task_lock_;
-
- Location last_posted_from_ = {};
- std::array<const void*, 4> last_task_backtrace_ = {};
-
- DISALLOW_COPY_AND_ASSIGN(TaskAnnotatorBacktraceIntegrationTest);
-};
-
-// Ensure the task backtrace populates correctly.
-TEST_F(TaskAnnotatorBacktraceIntegrationTest, SingleThreadedSimple) {
- MessageLoop loop;
- const Location location0 = FROM_HERE;
- const Location location1 = FROM_HERE;
- const Location location2 = FROM_HERE;
- const Location location3 = FROM_HERE;
- const Location location4 = FROM_HERE;
- const Location location5 = FROM_HERE;
-
- RunLoop run_loop;
-
- // Task 5 has tasks 4/3/2/1 as parents (task 0 isn't visible as only the
- // last 4 parents are kept).
- OnceClosure task5 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location5, FROM_HERE,
- ExpectedTrace({location4.program_counter(), location3.program_counter(),
- location2.program_counter(), location1.program_counter()}),
- run_loop.QuitClosure());
-
- // Task i=4/3/2/1/0 have tasks [0,i) as parents.
- OnceClosure task4 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location4, location5,
- ExpectedTrace({location3.program_counter(), location2.program_counter(),
- location1.program_counter(), location0.program_counter()}),
- std::move(task5));
- OnceClosure task3 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location3, location4,
- ExpectedTrace({location2.program_counter(), location1.program_counter(),
- location0.program_counter()}),
- std::move(task4));
- OnceClosure task2 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location2, location3,
- ExpectedTrace({location1.program_counter(), location0.program_counter()}),
- std::move(task3));
- OnceClosure task1 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location1, location2,
- ExpectedTrace({location0.program_counter()}), std::move(task2));
- OnceClosure task0 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location0, location1,
- ExpectedTrace({}), std::move(task1));
-
- loop.task_runner()->PostTask(location0, std::move(task0));
-
- run_loop.Run();
-}
-
-// Ensure it works when posting tasks across multiple threads managed by //base.
-TEST_F(TaskAnnotatorBacktraceIntegrationTest, MultipleThreads) {
- test::ScopedTaskEnvironment scoped_task_environment;
-
- // Use diverse task runners (a MessageLoop on the main thread, a TaskScheduler
- // based SequencedTaskRunner, and a TaskScheduler based
- // SingleThreadTaskRunner) to verify that TaskAnnotator can capture backtraces
- // for PostTasks back-and-forth between these.
- auto main_thread_a = ThreadTaskRunnerHandle::Get();
- auto task_runner_b = CreateSingleThreadTaskRunnerWithTraits({});
- auto task_runner_c = CreateSequencedTaskRunnerWithTraits(
- {base::MayBlock(), base::WithBaseSyncPrimitives()});
-
- const Location& location_a0 = FROM_HERE;
- const Location& location_a1 = FROM_HERE;
- const Location& location_a2 = FROM_HERE;
- const Location& location_a3 = FROM_HERE;
-
- const Location& location_b0 = FROM_HERE;
- const Location& location_b1 = FROM_HERE;
-
- const Location& location_c0 = FROM_HERE;
-
- RunLoop run_loop;
-
- // All tasks below happen in lock step by nature of being posted by the
- // previous one (plus the synchronous nature of RunTwo()) with the exception
- // of the follow-up local task to |task_b0_local|. This WaitableEvent ensures
- // it completes before |task_c0| runs to avoid racy invocations of
- // BeforeRunTask()+VerifyTraceAndPost().
- WaitableEvent lock_step(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // Here is the execution order generated below:
- // A: TA0 -> TA1 \ TA2
- // B: TB0L \ + TB0F \ Signal \ /
- // ---------\--/ \ /
- // \ \ /
- // C: Wait........ TC0 /
-
- // On task runner c, post a task back to main thread that verifies its trace
- // and terminates after one more self-post.
- OnceClosure task_a2 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), main_thread_a, location_a2, location_a3,
- ExpectedTrace(
- {location_c0.program_counter(), location_b0.program_counter(),
- location_a1.program_counter(), location_a0.program_counter()}),
- run_loop.QuitClosure());
- OnceClosure task_c0 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), main_thread_a, location_c0, location_a2,
- ExpectedTrace({location_b0.program_counter(),
- location_a1.program_counter(),
- location_a0.program_counter()}),
- std::move(task_a2));
-
- // On task runner b run two tasks that conceptually come from the same
- // location (managed via RunTwo().) One will post back to task runner b and
- // another will post to task runner c to test spawning multiple tasks on
- // different message loops. The task posted to task runner c will not get
- // location b1 whereas the one posted back to task runner b will.
- OnceClosure task_b0_fork = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPostWithBlocker,
- Unretained(this), task_runner_c, location_b0, location_c0,
- ExpectedTrace(
- {location_a1.program_counter(), location_a0.program_counter()}),
- std::move(task_c0), &lock_step);
- OnceClosure task_b0_local =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), task_runner_b, location_b0, location_b1,
- ExpectedTrace({location_a1.program_counter(),
- location_a0.program_counter()}),
- BindOnce(&WaitableEvent::Signal, Unretained(&lock_step)));
-
- OnceClosure task_a1 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), task_runner_b, location_a1, location_b0,
- ExpectedTrace({location_a0.program_counter()}),
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::RunTwo,
- std::move(task_b0_local), std::move(task_b0_fork)));
- OnceClosure task_a0 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), main_thread_a, location_a0, location_a1,
- ExpectedTrace({}), std::move(task_a1));
-
- main_thread_a->PostTask(location_a0, std::move(task_a0));
-
- run_loop.Run();
-}
-
-// Ensure nesting doesn't break the chain.
-TEST_F(TaskAnnotatorBacktraceIntegrationTest, SingleThreadedNested) {
- MessageLoop loop;
- const Location location0 = FROM_HERE;
- const Location location1 = FROM_HERE;
- const Location location2 = FROM_HERE;
- const Location location3 = FROM_HERE;
- const Location location4 = FROM_HERE;
- const Location location5 = FROM_HERE;
-
- RunLoop run_loop;
-
- // Task execution below looks like this, w.r.t. to RunLoop depths:
- // 1 : T0 \ + NRL1 \ ---------> T4 -> T5
- // 2 : ---------> T1 \ -> NRL2 \ ----> T2 -> T3 / + Quit /
- // 3 : ---------> DN /
-
- // NRL1 tests that tasks that occur at a different nesting depth than their
- // parent have a sane backtrace nonetheless (both ways).
-
- // NRL2 tests that posting T2 right after exiting the RunLoop (from the same
- // task) results in NRL2 being its parent (and not the DoNothing() task that
- // just ran -- which would have been the case if the "current task" wasn't
- // restored properly when returning from a task within a task).
-
- // In other words, this is regression test for a bug in the previous
- // implementation. In the current implementation, replacing
- // tls_for_current_pending_task->Set(previous_pending_task);
- // by
- // tls_for_current_pending_task->Set(nullptr);
- // at the end of TaskAnnotator::RunTask() makes this test fail.
-
- RunLoop nested_run_loop1(RunLoop::Type::kNestableTasksAllowed);
-
- // Expectations are the same as in SingleThreadedSimple test despite the
- // nested loop starting between tasks 0 and 1 and stopping between tasks 3 and
- // 4.
- OnceClosure task5 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location5, FROM_HERE,
- ExpectedTrace({location4.program_counter(), location3.program_counter(),
- location2.program_counter(), location1.program_counter()}),
- run_loop.QuitClosure());
- OnceClosure task4 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location4, location5,
- ExpectedTrace({location3.program_counter(), location2.program_counter(),
- location1.program_counter(), location0.program_counter()}),
- std::move(task5));
- OnceClosure task3 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location3, location4,
- ExpectedTrace({location2.program_counter(), location1.program_counter(),
- location0.program_counter()}),
- std::move(task4));
-
- OnceClosure run_task_3_then_quit_nested_loop1 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::RunTwo, std::move(task3),
- nested_run_loop1.QuitClosure());
-
- OnceClosure task2 = BindOnce(
- &TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location2, location3,
- ExpectedTrace({location1.program_counter(), location0.program_counter()}),
- std::move(run_task_3_then_quit_nested_loop1));
-
- // Task 1 is custom. It enters another nested RunLoop, has it do work and exit
- // before posting the next task. This confirms that |task1| is restored as the
- // current task before posting |task2| after returning from the nested loop.
- RunLoop nested_run_loop2(RunLoop::Type::kNestableTasksAllowed);
- OnceClosure task1 = BindOnce(
- [](RunLoop* nested_run_loop, const Location& location2,
- OnceClosure task2) {
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
- nested_run_loop->RunUntilIdle();
- ThreadTaskRunnerHandle::Get()->PostTask(location2, std::move(task2));
- },
- Unretained(&nested_run_loop2), location2, std::move(task2));
-
- OnceClosure task0 =
- BindOnce(&TaskAnnotatorBacktraceIntegrationTest::VerifyTraceAndPost,
- Unretained(this), loop.task_runner(), location0, location1,
- ExpectedTrace({}), std::move(task1));
-
- loop.task_runner()->PostTask(location0, std::move(task0));
- loop.task_runner()->PostTask(
- FROM_HERE, BindOnce(&RunLoop::Run, Unretained(&nested_run_loop1)));
-
- run_loop.Run();
-}
-
-} // 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 fc7fda4..0000000
--- a/base/debug/thread_heap_usage_tracker_unittest.cc
+++ /dev/null
@@ -1,556 +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 "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);
-}
-
-} // namespace debug
-} // namespace base
diff --git a/base/deferred_sequenced_task_runner_unittest.cc b/base/deferred_sequenced_task_runner_unittest.cc
deleted file mode 100644
index 5cb220f..0000000
--- 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/environment_unittest.cc b/base/environment_unittest.cc
deleted file mode 100644
index 79800ad..0000000
--- a/base/environment_unittest.cc
+++ /dev/null
@@ -1,171 +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/environment.h"
-
-#include <memory>
-
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-typedef PlatformTest EnvironmentTest;
-
-namespace base {
-
-namespace {
-
-constexpr char kValidEnvironmentVariable[] = "PATH";
-
-} // namespace
-
-TEST_F(EnvironmentTest, GetVar) {
- std::unique_ptr<Environment> env(Environment::Create());
- std::string env_value;
- EXPECT_TRUE(env->GetVar(kValidEnvironmentVariable, &env_value));
- EXPECT_NE(env_value, "");
-}
-
-TEST_F(EnvironmentTest, GetVarReverse) {
- std::unique_ptr<Environment> env(Environment::Create());
- const char kFooUpper[] = "FOO";
- const char kFooLower[] = "foo";
-
- // Set a variable in UPPER case.
- EXPECT_TRUE(env->SetVar(kFooUpper, kFooLower));
-
- // And then try to get this variable passing the lower case.
- std::string env_value;
- EXPECT_TRUE(env->GetVar(kFooLower, &env_value));
-
- EXPECT_STREQ(env_value.c_str(), kFooLower);
-
- EXPECT_TRUE(env->UnSetVar(kFooUpper));
-
- const char kBar[] = "bar";
- // Now do the opposite, set the variable in the lower case.
- EXPECT_TRUE(env->SetVar(kFooLower, kBar));
-
- // And then try to get this variable passing the UPPER case.
- EXPECT_TRUE(env->GetVar(kFooUpper, &env_value));
-
- EXPECT_STREQ(env_value.c_str(), kBar);
-
- EXPECT_TRUE(env->UnSetVar(kFooLower));
-}
-
-TEST_F(EnvironmentTest, HasVar) {
- std::unique_ptr<Environment> env(Environment::Create());
- EXPECT_TRUE(env->HasVar(kValidEnvironmentVariable));
-}
-
-TEST_F(EnvironmentTest, SetVar) {
- std::unique_ptr<Environment> env(Environment::Create());
-
- const char kFooUpper[] = "FOO";
- const char kFooLower[] = "foo";
- EXPECT_TRUE(env->SetVar(kFooUpper, kFooLower));
-
- // Now verify that the environment has the new variable.
- EXPECT_TRUE(env->HasVar(kFooUpper));
-
- std::string var_value;
- EXPECT_TRUE(env->GetVar(kFooUpper, &var_value));
- EXPECT_EQ(var_value, kFooLower);
-}
-
-TEST_F(EnvironmentTest, UnSetVar) {
- std::unique_ptr<Environment> env(Environment::Create());
-
- const char kFooUpper[] = "FOO";
- const char kFooLower[] = "foo";
- // First set some environment variable.
- EXPECT_TRUE(env->SetVar(kFooUpper, kFooLower));
-
- // Now verify that the environment has the new variable.
- EXPECT_TRUE(env->HasVar(kFooUpper));
-
- // Finally verify that the environment variable was erased.
- EXPECT_TRUE(env->UnSetVar(kFooUpper));
-
- // And check that the variable has been unset.
- EXPECT_FALSE(env->HasVar(kFooUpper));
-}
-
-#if defined(OS_WIN)
-
-TEST_F(EnvironmentTest, AlterEnvironment) {
- const wchar_t empty[] = L"\0";
- const wchar_t a2[] = L"A=2\0";
- EnvironmentMap changes;
- string16 e;
-
- e = AlterEnvironment(empty, changes);
- EXPECT_EQ(0, e[0]);
-
- changes[L"A"] = L"1";
- e = AlterEnvironment(empty, changes);
- EXPECT_EQ(string16(L"A=1\0\0", 5), e);
-
- changes.clear();
- changes[L"A"] = string16();
- e = AlterEnvironment(empty, changes);
- EXPECT_EQ(string16(L"\0\0", 2), e);
-
- changes.clear();
- e = AlterEnvironment(a2, changes);
- EXPECT_EQ(string16(L"A=2\0\0", 5), e);
-
- changes.clear();
- changes[L"A"] = L"1";
- e = AlterEnvironment(a2, changes);
- EXPECT_EQ(string16(L"A=1\0\0", 5), e);
-
- changes.clear();
- changes[L"A"] = string16();
- e = AlterEnvironment(a2, changes);
- EXPECT_EQ(string16(L"\0\0", 2), e);
-}
-
-#else
-
-TEST_F(EnvironmentTest, AlterEnvironment) {
- const char* const empty[] = {nullptr};
- const char* const a2[] = {"A=2", nullptr};
- EnvironmentMap changes;
- std::unique_ptr<char* []> e;
-
- e = AlterEnvironment(empty, changes);
- EXPECT_TRUE(e[0] == nullptr);
-
- changes["A"] = "1";
- e = AlterEnvironment(empty, changes);
- EXPECT_EQ(std::string("A=1"), e[0]);
- EXPECT_TRUE(e[1] == nullptr);
-
- changes.clear();
- changes["A"] = std::string();
- e = AlterEnvironment(empty, changes);
- EXPECT_TRUE(e[0] == nullptr);
-
- changes.clear();
- e = AlterEnvironment(a2, changes);
- EXPECT_EQ(std::string("A=2"), e[0]);
- EXPECT_TRUE(e[1] == nullptr);
-
- changes.clear();
- changes["A"] = "1";
- e = AlterEnvironment(a2, changes);
- EXPECT_EQ(std::string("A=1"), e[0]);
- EXPECT_TRUE(e[1] == nullptr);
-
- changes.clear();
- changes["A"] = std::string();
- e = AlterEnvironment(a2, changes);
- EXPECT_TRUE(e[0] == nullptr);
-}
-
-#endif
-
-} // namespace base
diff --git a/base/feature_list_unittest.cc b/base/feature_list_unittest.cc
deleted file mode 100644
index 164997a..0000000
--- a/base/feature_list_unittest.cc
+++ /dev/null
@@ -1,542 +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/feature_list.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-#include <utility>
-
-#include "base/format_macros.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/field_trial.h"
-#include "base/metrics/persistent_memory_allocator.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-constexpr char kFeatureOnByDefaultName[] = "OnByDefault";
-struct Feature kFeatureOnByDefault {
- kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
-};
-
-constexpr char kFeatureOffByDefaultName[] = "OffByDefault";
-struct Feature kFeatureOffByDefault {
- kFeatureOffByDefaultName, FEATURE_DISABLED_BY_DEFAULT
-};
-
-std::string SortFeatureListString(const std::string& feature_list) {
- std::vector<base::StringPiece> features =
- FeatureList::SplitFeatureListString(feature_list);
- std::sort(features.begin(), features.end());
- return JoinString(features, ",");
-}
-
-} // namespace
-
-class FeatureListTest : public testing::Test {
- public:
- FeatureListTest() : feature_list_(nullptr) {
- RegisterFeatureListInstance(WrapUnique(new FeatureList));
- }
- ~FeatureListTest() override { ClearFeatureListInstance(); }
-
- void RegisterFeatureListInstance(std::unique_ptr<FeatureList> feature_list) {
- FeatureList::ClearInstanceForTesting();
- feature_list_ = feature_list.get();
- FeatureList::SetInstance(std::move(feature_list));
- }
- void ClearFeatureListInstance() {
- FeatureList::ClearInstanceForTesting();
- feature_list_ = nullptr;
- }
-
- FeatureList* feature_list() { return feature_list_; }
-
- private:
- // Weak. Owned by the FeatureList::SetInstance().
- FeatureList* feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(FeatureListTest);
-};
-
-TEST_F(FeatureListTest, DefaultStates) {
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
-}
-
-TEST_F(FeatureListTest, InitializeFromCommandLine) {
- struct {
- const char* enable_features;
- const char* disable_features;
- bool expected_feature_on_state;
- bool expected_feature_off_state;
- } test_cases[] = {
- {"", "", true, false},
- {"OffByDefault", "", true, true},
- {"OffByDefault", "OnByDefault", false, true},
- {"OnByDefault,OffByDefault", "", true, true},
- {"", "OnByDefault,OffByDefault", false, false},
- // In the case an entry is both, disable takes precedence.
- {"OnByDefault", "OnByDefault,OffByDefault", false, false},
- };
-
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
- const auto& test_case = test_cases[i];
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
- test_case.enable_features,
- test_case.disable_features));
-
- ClearFeatureListInstance();
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine(test_case.enable_features,
- test_case.disable_features);
- RegisterFeatureListInstance(std::move(feature_list));
-
- EXPECT_EQ(test_case.expected_feature_on_state,
- FeatureList::IsEnabled(kFeatureOnByDefault))
- << i;
- EXPECT_EQ(test_case.expected_feature_off_state,
- FeatureList::IsEnabled(kFeatureOffByDefault))
- << i;
- }
-}
-
-TEST_F(FeatureListTest, CheckFeatureIdentity) {
- // Tests that CheckFeatureIdentity() correctly detects when two different
- // structs with the same feature name are passed to it.
-
- // Call it twice for each feature at the top of the file, since the first call
- // makes it remember the entry and the second call will verify it.
- EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault));
- EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault));
- EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOffByDefault));
- EXPECT_TRUE(feature_list()->CheckFeatureIdentity(kFeatureOffByDefault));
-
- // Now, call it with a distinct struct for |kFeatureOnByDefaultName|, which
- // should return false.
- struct Feature kFeatureOnByDefault2 {
- kFeatureOnByDefaultName, FEATURE_ENABLED_BY_DEFAULT
- };
- EXPECT_FALSE(feature_list()->CheckFeatureIdentity(kFeatureOnByDefault2));
-}
-
-TEST_F(FeatureListTest, FieldTrialOverrides) {
- struct {
- FeatureList::OverrideState trial1_state;
- FeatureList::OverrideState trial2_state;
- } test_cases[] = {
- {FeatureList::OVERRIDE_DISABLE_FEATURE,
- FeatureList::OVERRIDE_DISABLE_FEATURE},
- {FeatureList::OVERRIDE_DISABLE_FEATURE,
- FeatureList::OVERRIDE_ENABLE_FEATURE},
- {FeatureList::OVERRIDE_ENABLE_FEATURE,
- FeatureList::OVERRIDE_DISABLE_FEATURE},
- {FeatureList::OVERRIDE_ENABLE_FEATURE,
- FeatureList::OVERRIDE_ENABLE_FEATURE},
- };
-
- FieldTrial::ActiveGroup active_group;
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
- const auto& test_case = test_cases[i];
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]", i));
-
- ClearFeatureListInstance();
-
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
-
- FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
- FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
- feature_list->RegisterFieldTrialOverride(kFeatureOnByDefaultName,
- test_case.trial1_state, trial1);
- feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
- test_case.trial2_state, trial2);
- RegisterFeatureListInstance(std::move(feature_list));
-
- // Initially, neither trial should be active.
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
-
- const bool expected_enabled_1 =
- (test_case.trial1_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
- EXPECT_EQ(expected_enabled_1, FeatureList::IsEnabled(kFeatureOnByDefault));
- // The above should have activated |trial1|.
- EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
-
- const bool expected_enabled_2 =
- (test_case.trial2_state == FeatureList::OVERRIDE_ENABLE_FEATURE);
- EXPECT_EQ(expected_enabled_2, FeatureList::IsEnabled(kFeatureOffByDefault));
- // The above should have activated |trial2|.
- EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
- EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
- }
-}
-
-TEST_F(FeatureListTest, FieldTrialAssociateUseDefault) {
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
-
- FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
- FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
- feature_list->RegisterFieldTrialOverride(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
- feature_list->RegisterFieldTrialOverride(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
- RegisterFeatureListInstance(std::move(feature_list));
-
- // Initially, neither trial should be active.
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial1->trial_name()));
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
-
- // Check the feature enabled state is its default.
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
- // The above should have activated |trial1|.
- EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial2->trial_name()));
-
- // Check the feature enabled state is its default.
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
- // The above should have activated |trial2|.
- EXPECT_TRUE(FieldTrialList::IsTrialActive(trial1->trial_name()));
- EXPECT_TRUE(FieldTrialList::IsTrialActive(trial2->trial_name()));
-}
-
-TEST_F(FeatureListTest, CommandLineTakesPrecedenceOverFieldTrial) {
- ClearFeatureListInstance();
-
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
-
- // The feature is explicitly enabled on the command-line.
- feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
-
- // But the FieldTrial would set the feature to disabled.
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample2", "A");
- feature_list->RegisterFieldTrialOverride(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
- RegisterFeatureListInstance(std::move(feature_list));
-
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
- // Command-line should take precedence.
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
- // Since the feature is on due to the command-line, and not as a result of the
- // field trial, the field trial should not be activated (since the Associate*
- // API wasn't used.)
- EXPECT_FALSE(FieldTrialList::IsTrialActive(trial->trial_name()));
-}
-
-TEST_F(FeatureListTest, IsFeatureOverriddenFromCommandLine) {
- ClearFeatureListInstance();
-
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
-
- // No features are overridden from the command line yet
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
-
- // Now, enable |kFeatureOffByDefaultName| via the command-line.
- feature_list->InitializeFromCommandLine(kFeatureOffByDefaultName, "");
-
- // It should now be overridden for the enabled group.
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
- EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
-
- // Register a field trial to associate with the feature and ensure that the
- // results are still the same.
- feature_list->AssociateReportingFieldTrial(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
- FieldTrialList::CreateFieldTrial("Trial1", "A"));
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
- EXPECT_TRUE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
-
- // Now, register a field trial to override |kFeatureOnByDefaultName| state
- // and check that the function still returns false for that feature.
- feature_list->RegisterFieldTrialOverride(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
- FieldTrialList::CreateFieldTrial("Trial2", "A"));
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
- EXPECT_FALSE(feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
- RegisterFeatureListInstance(std::move(feature_list));
-
- // Check the expected feature states for good measure.
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
-}
-
-TEST_F(FeatureListTest, AssociateReportingFieldTrial) {
- struct {
- const char* enable_features;
- const char* disable_features;
- bool expected_enable_trial_created;
- bool expected_disable_trial_created;
- } test_cases[] = {
- // If no enable/disable flags are specified, no trials should be created.
- {"", "", false, false},
- // Enabling the feature should result in the enable trial created.
- {kFeatureOffByDefaultName, "", true, false},
- // Disabling the feature should result in the disable trial created.
- {"", kFeatureOffByDefaultName, false, true},
- };
-
- const char kTrialName[] = "ForcingTrial";
- const char kForcedOnGroupName[] = "ForcedOn";
- const char kForcedOffGroupName[] = "ForcedOff";
-
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
- const auto& test_case = test_cases[i];
- SCOPED_TRACE(base::StringPrintf("Test[%" PRIuS "]: [%s] [%s]", i,
- test_case.enable_features,
- test_case.disable_features));
-
- ClearFeatureListInstance();
-
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine(test_case.enable_features,
- test_case.disable_features);
-
- FieldTrial* enable_trial = nullptr;
- if (feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE)) {
- enable_trial = base::FieldTrialList::CreateFieldTrial(kTrialName,
- kForcedOnGroupName);
- feature_list->AssociateReportingFieldTrial(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE,
- enable_trial);
- }
- FieldTrial* disable_trial = nullptr;
- if (feature_list->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE)) {
- disable_trial = base::FieldTrialList::CreateFieldTrial(
- kTrialName, kForcedOffGroupName);
- feature_list->AssociateReportingFieldTrial(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE,
- disable_trial);
- }
- EXPECT_EQ(test_case.expected_enable_trial_created, enable_trial != nullptr);
- EXPECT_EQ(test_case.expected_disable_trial_created,
- disable_trial != nullptr);
- RegisterFeatureListInstance(std::move(feature_list));
-
- EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
- if (disable_trial) {
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
- EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
- EXPECT_EQ(kForcedOffGroupName, disable_trial->group_name());
- } else if (enable_trial) {
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
- EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
- EXPECT_EQ(kForcedOnGroupName, enable_trial->group_name());
- }
- }
-}
-
-TEST_F(FeatureListTest, GetFeatureOverrides) {
- ClearFeatureListInstance();
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine("A,X", "D");
-
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
- feature_list->RegisterFieldTrialOverride(kFeatureOffByDefaultName,
- FeatureList::OVERRIDE_ENABLE_FEATURE,
- trial);
-
- RegisterFeatureListInstance(std::move(feature_list));
-
- std::string enable_features;
- std::string disable_features;
- FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
- &disable_features);
- EXPECT_EQ("A,OffByDefault<Trial,X", SortFeatureListString(enable_features));
- EXPECT_EQ("D", SortFeatureListString(disable_features));
-
- FeatureList::GetInstance()->GetCommandLineFeatureOverrides(&enable_features,
- &disable_features);
- EXPECT_EQ("A,X", SortFeatureListString(enable_features));
- EXPECT_EQ("D", SortFeatureListString(disable_features));
-}
-
-TEST_F(FeatureListTest, GetFeatureOverrides_UseDefault) {
- ClearFeatureListInstance();
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine("A,X", "D");
-
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
- feature_list->RegisterFieldTrialOverride(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
-
- RegisterFeatureListInstance(std::move(feature_list));
-
- std::string enable_features;
- std::string disable_features;
- FeatureList::GetInstance()->GetFeatureOverrides(&enable_features,
- &disable_features);
- EXPECT_EQ("*OffByDefault<Trial,A,X", SortFeatureListString(enable_features));
- EXPECT_EQ("D", SortFeatureListString(disable_features));
-}
-
-TEST_F(FeatureListTest, GetFieldTrial) {
- ClearFeatureListInstance();
- FieldTrialList field_trial_list(nullptr);
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial", "Group");
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->RegisterFieldTrialOverride(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial);
- RegisterFeatureListInstance(std::move(feature_list));
-
- EXPECT_EQ(trial, FeatureList::GetFieldTrial(kFeatureOnByDefault));
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kFeatureOffByDefault));
-}
-
-TEST_F(FeatureListTest, InitializeFromCommandLine_WithFieldTrials) {
- ClearFeatureListInstance();
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial("Trial", "Group");
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine("A,OffByDefault<Trial,X", "D");
- RegisterFeatureListInstance(std::move(feature_list));
-
- EXPECT_FALSE(FieldTrialList::IsTrialActive("Trial"));
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOffByDefault));
- EXPECT_TRUE(FieldTrialList::IsTrialActive("Trial"));
-}
-
-TEST_F(FeatureListTest, InitializeFromCommandLine_UseDefault) {
- ClearFeatureListInstance();
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial("T1", "Group");
- FieldTrialList::CreateFieldTrial("T2", "Group");
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine(
- "A,*OffByDefault<T1,*OnByDefault<T2,X", "D");
- RegisterFeatureListInstance(std::move(feature_list));
-
- EXPECT_FALSE(FieldTrialList::IsTrialActive("T1"));
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
- EXPECT_TRUE(FieldTrialList::IsTrialActive("T1"));
-
- EXPECT_FALSE(FieldTrialList::IsTrialActive("T2"));
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
- EXPECT_TRUE(FieldTrialList::IsTrialActive("T2"));
-}
-
-TEST_F(FeatureListTest, InitializeInstance) {
- ClearFeatureListInstance();
-
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
- FeatureList::SetInstance(std::move(feature_list));
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
-
- // Initialize from command line if we haven't yet.
- FeatureList::InitializeInstance("", kFeatureOnByDefaultName);
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
-
- // Do not initialize from commandline if we have already.
- FeatureList::InitializeInstance(kFeatureOffByDefaultName, "");
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOnByDefault));
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
-}
-
-TEST_F(FeatureListTest, UninitializedInstance_IsEnabledReturnsFalse) {
- ClearFeatureListInstance();
- // This test case simulates the calling pattern found in code which does not
- // explicitly initialize the features list.
- // All IsEnabled() calls should return the default value in this scenario.
- EXPECT_EQ(nullptr, FeatureList::GetInstance());
- EXPECT_TRUE(FeatureList::IsEnabled(kFeatureOnByDefault));
- EXPECT_EQ(nullptr, FeatureList::GetInstance());
- EXPECT_FALSE(FeatureList::IsEnabled(kFeatureOffByDefault));
-}
-
-TEST_F(FeatureListTest, StoreAndRetrieveFeaturesFromSharedMemory) {
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-
- // Create some overrides.
- feature_list->RegisterOverride(kFeatureOffByDefaultName,
- FeatureList::OVERRIDE_ENABLE_FEATURE, nullptr);
- feature_list->RegisterOverride(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE, nullptr);
- feature_list->FinalizeInitialization();
-
- // Create an allocator and store the overrides.
- std::unique_ptr<SharedMemory> shm(new SharedMemory());
- shm->CreateAndMapAnonymous(4 << 10);
- SharedPersistentMemoryAllocator allocator(std::move(shm), 1, "", false);
- feature_list->AddFeaturesToAllocator(&allocator);
-
- std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
-
- // Check that the new feature list is empty.
- EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
- EXPECT_FALSE(feature_list2->IsFeatureOverriddenFromCommandLine(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
-
- feature_list2->InitializeFromSharedMemory(&allocator);
- // Check that the new feature list now has 2 overrides.
- EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_ENABLE_FEATURE));
- EXPECT_TRUE(feature_list2->IsFeatureOverriddenFromCommandLine(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_DISABLE_FEATURE));
-}
-
-TEST_F(FeatureListTest, StoreAndRetrieveAssociatedFeaturesFromSharedMemory) {
- FieldTrialList field_trial_list(nullptr);
- std::unique_ptr<base::FeatureList> feature_list(new base::FeatureList);
-
- // Create some overrides.
- FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("TrialExample1", "A");
- FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("TrialExample2", "B");
- feature_list->RegisterFieldTrialOverride(
- kFeatureOnByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial1);
- feature_list->RegisterFieldTrialOverride(
- kFeatureOffByDefaultName, FeatureList::OVERRIDE_USE_DEFAULT, trial2);
- feature_list->FinalizeInitialization();
-
- // Create an allocator and store the overrides.
- std::unique_ptr<SharedMemory> shm(new SharedMemory());
- shm->CreateAndMapAnonymous(4 << 10);
- SharedPersistentMemoryAllocator allocator(std::move(shm), 1, "", false);
- feature_list->AddFeaturesToAllocator(&allocator);
-
- std::unique_ptr<base::FeatureList> feature_list2(new base::FeatureList);
- feature_list2->InitializeFromSharedMemory(&allocator);
- feature_list2->FinalizeInitialization();
-
- // Check that the field trials are still associated.
- FieldTrial* associated_trial1 =
- feature_list2->GetAssociatedFieldTrial(kFeatureOnByDefault);
- FieldTrial* associated_trial2 =
- feature_list2->GetAssociatedFieldTrial(kFeatureOffByDefault);
- EXPECT_EQ(associated_trial1, trial1);
- EXPECT_EQ(associated_trial2, trial2);
-}
-
-} // namespace base
diff --git a/base/file_version_info_win_unittest.cc b/base/file_version_info_win_unittest.cc
deleted file mode 100644
index a4acc4c..0000000
--- a/base/file_version_info_win_unittest.cc
+++ /dev/null
@@ -1,175 +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/file_version_info_win.h"
-
-#include <windows.h>
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/file_version_info.h"
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/path_service.h"
-#include "base/scoped_native_library.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::FilePath;
-
-namespace {
-
-FilePath GetTestDataPath() {
- FilePath path;
- base::PathService::Get(base::DIR_SOURCE_ROOT, &path);
- path = path.AppendASCII("base");
- path = path.AppendASCII("test");
- path = path.AppendASCII("data");
- path = path.AppendASCII("file_version_info_unittest");
- return path;
-}
-
-class FileVersionInfoFactory {
- public:
- explicit FileVersionInfoFactory(const FilePath& path) : path_(path) {}
-
- std::unique_ptr<FileVersionInfo> Create() const {
- return base::WrapUnique(FileVersionInfo::CreateFileVersionInfo(path_));
- }
-
- private:
- const FilePath path_;
-
- DISALLOW_COPY_AND_ASSIGN(FileVersionInfoFactory);
-};
-
-class FileVersionInfoForModuleFactory {
- public:
- explicit FileVersionInfoForModuleFactory(const FilePath& path)
- // Load the library with LOAD_LIBRARY_AS_IMAGE_RESOURCE since it shouldn't
- // be executed.
- : library_(::LoadLibraryEx(path.value().c_str(),
- nullptr,
- LOAD_LIBRARY_AS_IMAGE_RESOURCE)) {
- EXPECT_TRUE(library_.is_valid());
- }
-
- std::unique_ptr<FileVersionInfo> Create() const {
- return base::WrapUnique(
- FileVersionInfo::CreateFileVersionInfoForModule(library_.get()));
- }
-
- private:
- const base::ScopedNativeLibrary library_;
-
- DISALLOW_COPY_AND_ASSIGN(FileVersionInfoForModuleFactory);
-};
-
-template <typename T>
-class FileVersionInfoTest : public testing::Test {};
-
-using FileVersionInfoFactories =
- ::testing::Types<FileVersionInfoFactory, FileVersionInfoForModuleFactory>;
-
-} // namespace
-
-TYPED_TEST_CASE(FileVersionInfoTest, FileVersionInfoFactories);
-
-TYPED_TEST(FileVersionInfoTest, HardCodedProperties) {
- const wchar_t kDLLName[] = {L"FileVersionInfoTest1.dll"};
-
- const wchar_t* const kExpectedValues[15] = {
- // FileVersionInfoTest.dll
- L"Goooooogle", // company_name
- L"Google", // company_short_name
- L"This is the product name", // product_name
- L"This is the product short name", // product_short_name
- L"The Internal Name", // internal_name
- L"4.3.2.1", // product_version
- L"Private build property", // private_build
- L"Special build property", // special_build
- L"This is a particularly interesting comment", // comments
- L"This is the original filename", // original_filename
- L"This is my file description", // file_description
- L"1.2.3.4", // file_version
- L"This is the legal copyright", // legal_copyright
- L"This is the legal trademarks", // legal_trademarks
- L"This is the last change", // last_change
- };
-
- FilePath dll_path = GetTestDataPath();
- dll_path = dll_path.Append(kDLLName);
-
- TypeParam factory(dll_path);
- std::unique_ptr<FileVersionInfo> version_info(factory.Create());
- ASSERT_TRUE(version_info);
-
- int j = 0;
- EXPECT_EQ(kExpectedValues[j++], version_info->company_name());
- EXPECT_EQ(kExpectedValues[j++], version_info->company_short_name());
- EXPECT_EQ(kExpectedValues[j++], version_info->product_name());
- EXPECT_EQ(kExpectedValues[j++], version_info->product_short_name());
- EXPECT_EQ(kExpectedValues[j++], version_info->internal_name());
- EXPECT_EQ(kExpectedValues[j++], version_info->product_version());
- EXPECT_EQ(kExpectedValues[j++], version_info->private_build());
- EXPECT_EQ(kExpectedValues[j++], version_info->special_build());
- EXPECT_EQ(kExpectedValues[j++], version_info->comments());
- EXPECT_EQ(kExpectedValues[j++], version_info->original_filename());
- EXPECT_EQ(kExpectedValues[j++], version_info->file_description());
- EXPECT_EQ(kExpectedValues[j++], version_info->file_version());
- EXPECT_EQ(kExpectedValues[j++], version_info->legal_copyright());
- EXPECT_EQ(kExpectedValues[j++], version_info->legal_trademarks());
- EXPECT_EQ(kExpectedValues[j++], version_info->last_change());
-}
-
-TYPED_TEST(FileVersionInfoTest, IsOfficialBuild) {
- constexpr struct {
- const wchar_t* const dll_name;
- const bool is_official_build;
- } kTestItems[]{
- {L"FileVersionInfoTest1.dll", true}, {L"FileVersionInfoTest2.dll", false},
- };
-
- for (const auto& test_item : kTestItems) {
- const FilePath dll_path = GetTestDataPath().Append(test_item.dll_name);
-
- TypeParam factory(dll_path);
- std::unique_ptr<FileVersionInfo> version_info(factory.Create());
- ASSERT_TRUE(version_info);
-
- EXPECT_EQ(test_item.is_official_build, version_info->is_official_build());
- }
-}
-
-TYPED_TEST(FileVersionInfoTest, CustomProperties) {
- FilePath dll_path = GetTestDataPath();
- dll_path = dll_path.AppendASCII("FileVersionInfoTest1.dll");
-
- TypeParam factory(dll_path);
- std::unique_ptr<FileVersionInfo> version_info(factory.Create());
- ASSERT_TRUE(version_info);
-
- // Test few existing properties.
- std::wstring str;
- FileVersionInfoWin* version_info_win =
- static_cast<FileVersionInfoWin*>(version_info.get());
- EXPECT_TRUE(version_info_win->GetValue(L"Custom prop 1", &str));
- EXPECT_EQ(L"Un", str);
- EXPECT_EQ(L"Un", version_info_win->GetStringValue(L"Custom prop 1"));
-
- EXPECT_TRUE(version_info_win->GetValue(L"Custom prop 2", &str));
- EXPECT_EQ(L"Deux", str);
- EXPECT_EQ(L"Deux", version_info_win->GetStringValue(L"Custom prop 2"));
-
- EXPECT_TRUE(version_info_win->GetValue(L"Custom prop 3", &str));
- EXPECT_EQ(L"1600 Amphitheatre Parkway Mountain View, CA 94043", str);
- EXPECT_EQ(L"1600 Amphitheatre Parkway Mountain View, CA 94043",
- version_info_win->GetStringValue(L"Custom prop 3"));
-
- // Test an non-existing property.
- EXPECT_FALSE(version_info_win->GetValue(L"Unknown property", &str));
- EXPECT_EQ(L"", version_info_win->GetStringValue(L"Unknown property"));
-}
diff --git a/base/files/dir_reader_posix_unittest.cc b/base/files/dir_reader_posix_unittest.cc
deleted file mode 100644
index f82619b..0000000
--- a/base/files/dir_reader_posix_unittest.cc
+++ /dev/null
@@ -1,95 +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/dir_reader_posix.h"
-
-#include <fcntl.h>
-#include <limits.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_ANDROID)
-#include "base/os_compat_android.h"
-#endif
-
-namespace base {
-
-TEST(DirReaderPosixUnittest, Read) {
- static const unsigned kNumFiles = 100;
-
- if (DirReaderPosix::IsFallback())
- return;
-
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- const char* dir = temp_dir.GetPath().value().c_str();
- ASSERT_TRUE(dir);
-
- char wdbuf[PATH_MAX];
- PCHECK(getcwd(wdbuf, PATH_MAX));
-
- PCHECK(chdir(dir) == 0);
-
- for (unsigned i = 0; i < kNumFiles; i++) {
- char buf[16];
- snprintf(buf, sizeof(buf), "%d", i);
- const int fd = open(buf, O_CREAT | O_RDONLY | O_EXCL, 0600);
- PCHECK(fd >= 0);
- PCHECK(close(fd) == 0);
- }
-
- std::set<unsigned> seen;
-
- DirReaderPosix reader(dir);
- EXPECT_TRUE(reader.IsValid());
-
- if (!reader.IsValid())
- return;
-
- bool seen_dot = false, seen_dotdot = false;
-
- for (; reader.Next(); ) {
- if (strcmp(reader.name(), ".") == 0) {
- seen_dot = true;
- continue;
- }
- if (strcmp(reader.name(), "..") == 0) {
- seen_dotdot = true;
- continue;
- }
-
- SCOPED_TRACE(testing::Message() << "reader.name(): " << reader.name());
-
- char *endptr;
- const unsigned long value = strtoul(reader.name(), &endptr, 10);
-
- EXPECT_FALSE(*endptr);
- EXPECT_LT(value, kNumFiles);
- EXPECT_EQ(0u, seen.count(value));
- seen.insert(value);
- }
-
- for (unsigned i = 0; i < kNumFiles; i++) {
- char buf[16];
- snprintf(buf, sizeof(buf), "%d", i);
- PCHECK(unlink(buf) == 0);
- }
-
- PCHECK(rmdir(dir) == 0);
-
- PCHECK(chdir(wdbuf) == 0);
-
- EXPECT_TRUE(seen_dot);
- EXPECT_TRUE(seen_dotdot);
- EXPECT_EQ(kNumFiles, seen.size());
-}
-
-} // namespace base
diff --git a/base/files/file_descriptor_watcher_posix_unittest.cc b/base/files/file_descriptor_watcher_posix_unittest.cc
deleted file mode 100644
index 8fc57ce..0000000
--- a/base/files/file_descriptor_watcher_posix_unittest.cc
+++ /dev/null
@@ -1,318 +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/files/file_descriptor_watcher_posix.h"
-
-#include <unistd.h>
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/files/file_util.h"
-#include "base/macros.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/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_checker_impl.h"
-#include "build_config.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class Mock {
- public:
- Mock() = default;
-
- MOCK_METHOD0(ReadableCallback, void());
- MOCK_METHOD0(WritableCallback, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Mock);
-};
-
-enum class FileDescriptorWatcherTestType {
- MESSAGE_LOOP_FOR_IO_ON_MAIN_THREAD,
- MESSAGE_LOOP_FOR_IO_ON_OTHER_THREAD,
-};
-
-class FileDescriptorWatcherTest
- : public testing::TestWithParam<FileDescriptorWatcherTestType> {
- public:
- FileDescriptorWatcherTest()
- : message_loop_(GetParam() == FileDescriptorWatcherTestType::
- MESSAGE_LOOP_FOR_IO_ON_MAIN_THREAD
- ? new MessageLoopForIO
- : new MessageLoop),
- other_thread_("FileDescriptorWatcherTest_OtherThread") {}
- ~FileDescriptorWatcherTest() override = default;
-
- void SetUp() override {
- ASSERT_EQ(0, pipe(pipe_fds_));
-
- MessageLoop* message_loop_for_io;
- if (GetParam() ==
- FileDescriptorWatcherTestType::MESSAGE_LOOP_FOR_IO_ON_OTHER_THREAD) {
- Thread::Options options;
- options.message_loop_type = MessageLoop::TYPE_IO;
- ASSERT_TRUE(other_thread_.StartWithOptions(options));
- message_loop_for_io = other_thread_.message_loop();
- } else {
- message_loop_for_io = message_loop_.get();
- }
-
- ASSERT_TRUE(message_loop_for_io->IsType(MessageLoop::TYPE_IO));
- file_descriptor_watcher_ = std::make_unique<FileDescriptorWatcher>(
- static_cast<MessageLoopForIO*>(message_loop_for_io));
- }
-
- void TearDown() override {
- if (GetParam() ==
- FileDescriptorWatcherTestType::MESSAGE_LOOP_FOR_IO_ON_MAIN_THREAD &&
- message_loop_) {
- // Allow the delete task posted by the Controller's destructor to run.
- base::RunLoop().RunUntilIdle();
- }
-
- // Ensure that OtherThread is done processing before closing fds.
- other_thread_.Stop();
-
- EXPECT_EQ(0, IGNORE_EINTR(close(pipe_fds_[0])));
- EXPECT_EQ(0, IGNORE_EINTR(close(pipe_fds_[1])));
- }
-
- protected:
- int read_file_descriptor() const { return pipe_fds_[0]; }
- int write_file_descriptor() const { return pipe_fds_[1]; }
-
- // Waits for a short delay and run pending tasks.
- void WaitAndRunPendingTasks() {
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- RunLoop().RunUntilIdle();
- }
-
- // Registers ReadableCallback() to be called on |mock_| when
- // read_file_descriptor() is readable without blocking.
- std::unique_ptr<FileDescriptorWatcher::Controller> WatchReadable() {
- std::unique_ptr<FileDescriptorWatcher::Controller> controller =
- FileDescriptorWatcher::WatchReadable(
- read_file_descriptor(),
- Bind(&Mock::ReadableCallback, Unretained(&mock_)));
- EXPECT_TRUE(controller);
-
- // Unless read_file_descriptor() was readable before the callback was
- // registered, this shouldn't do anything.
- WaitAndRunPendingTasks();
-
- return controller;
- }
-
- // Registers WritableCallback() to be called on |mock_| when
- // write_file_descriptor() is writable without blocking.
- std::unique_ptr<FileDescriptorWatcher::Controller> WatchWritable() {
- std::unique_ptr<FileDescriptorWatcher::Controller> controller =
- FileDescriptorWatcher::WatchWritable(
- write_file_descriptor(),
- Bind(&Mock::WritableCallback, Unretained(&mock_)));
- EXPECT_TRUE(controller);
- return controller;
- }
-
- void WriteByte() {
- constexpr char kByte = '!';
- ASSERT_TRUE(
- WriteFileDescriptor(write_file_descriptor(), &kByte, sizeof(kByte)));
- }
-
- void ReadByte() {
- // This is always called as part of the WatchReadable() callback, which
- // should run on the main thread.
- EXPECT_TRUE(thread_checker_.CalledOnValidThread());
-
- char buffer;
- ASSERT_TRUE(ReadFromFD(read_file_descriptor(), &buffer, sizeof(buffer)));
- }
-
- // Mock on wich callbacks are invoked.
- testing::StrictMock<Mock> mock_;
-
- // MessageLoop bound to the main thread.
- std::unique_ptr<MessageLoop> message_loop_;
-
- // Thread running a MessageLoopForIO. Used when the test type is
- // MESSAGE_LOOP_FOR_IO_ON_OTHER_THREAD.
- Thread other_thread_;
-
- private:
- // Determines which MessageLoopForIO is used to watch file descriptors for
- // which callbacks are registered on the main thread.
- std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher_;
-
- // Watched file descriptors.
- int pipe_fds_[2];
-
- // Used to verify that callbacks run on the thread on which they are
- // registered.
- ThreadCheckerImpl thread_checker_;
-
- DISALLOW_COPY_AND_ASSIGN(FileDescriptorWatcherTest);
-};
-
-} // namespace
-
-TEST_P(FileDescriptorWatcherTest, WatchWritable) {
- auto controller = WatchWritable();
-
- // The write end of a newly created pipe is immediately writable.
- RunLoop run_loop;
- EXPECT_CALL(mock_, WritableCallback())
- .WillOnce(testing::Invoke(&run_loop, &RunLoop::Quit));
- run_loop.Run();
-}
-
-TEST_P(FileDescriptorWatcherTest, WatchReadableOneByte) {
- auto controller = WatchReadable();
-
- // Write 1 byte to the pipe, making it readable without blocking. Expect one
- // call to ReadableCallback() which will read 1 byte from the pipe.
- WriteByte();
- RunLoop run_loop;
- EXPECT_CALL(mock_, ReadableCallback())
- .WillOnce(testing::Invoke([this, &run_loop]() {
- ReadByte();
- run_loop.Quit();
- }));
- run_loop.Run();
- testing::Mock::VerifyAndClear(&mock_);
-
- // No more call to ReadableCallback() is expected.
- WaitAndRunPendingTasks();
-}
-
-TEST_P(FileDescriptorWatcherTest, WatchReadableTwoBytes) {
- auto controller = WatchReadable();
-
- // Write 2 bytes to the pipe. Expect two calls to ReadableCallback() which
- // will each read 1 byte from the pipe.
- WriteByte();
- WriteByte();
- RunLoop run_loop;
- EXPECT_CALL(mock_, ReadableCallback())
- .WillOnce(testing::Invoke([this]() { ReadByte(); }))
- .WillOnce(testing::Invoke([this, &run_loop]() {
- ReadByte();
- run_loop.Quit();
- }));
- run_loop.Run();
- testing::Mock::VerifyAndClear(&mock_);
-
- // No more call to ReadableCallback() is expected.
- WaitAndRunPendingTasks();
-}
-
-TEST_P(FileDescriptorWatcherTest, WatchReadableByteWrittenFromCallback) {
- auto controller = WatchReadable();
-
- // Write 1 byte to the pipe. Expect one call to ReadableCallback() from which
- // 1 byte is read and 1 byte is written to the pipe. Then, expect another call
- // to ReadableCallback() from which the remaining byte is read from the pipe.
- WriteByte();
- RunLoop run_loop;
- EXPECT_CALL(mock_, ReadableCallback())
- .WillOnce(testing::Invoke([this]() {
- ReadByte();
- WriteByte();
- }))
- .WillOnce(testing::Invoke([this, &run_loop]() {
- ReadByte();
- run_loop.Quit();
- }));
- run_loop.Run();
- testing::Mock::VerifyAndClear(&mock_);
-
- // No more call to ReadableCallback() is expected.
- WaitAndRunPendingTasks();
-}
-
-TEST_P(FileDescriptorWatcherTest, DeleteControllerFromCallback) {
- auto controller = WatchReadable();
-
- // Write 1 byte to the pipe. Expect one call to ReadableCallback() from which
- // |controller| is deleted.
- WriteByte();
- RunLoop run_loop;
- EXPECT_CALL(mock_, ReadableCallback())
- .WillOnce(testing::Invoke([&run_loop, &controller]() {
- controller = nullptr;
- run_loop.Quit();
- }));
- run_loop.Run();
- testing::Mock::VerifyAndClear(&mock_);
-
- // Since |controller| has been deleted, no call to ReadableCallback() is
- // expected even though the pipe is still readable without blocking.
- WaitAndRunPendingTasks();
-}
-
-TEST_P(FileDescriptorWatcherTest,
- DeleteControllerBeforeFileDescriptorReadable) {
- auto controller = WatchReadable();
-
- // Cancel the watch.
- controller = nullptr;
-
- // Write 1 byte to the pipe to make it readable without blocking.
- WriteByte();
-
- // No call to ReadableCallback() is expected.
- WaitAndRunPendingTasks();
-}
-
-TEST_P(FileDescriptorWatcherTest, DeleteControllerAfterFileDescriptorReadable) {
- auto controller = WatchReadable();
-
- // Write 1 byte to the pipe to make it readable without blocking.
- WriteByte();
-
- // Cancel the watch.
- controller = nullptr;
-
- // No call to ReadableCallback() is expected.
- WaitAndRunPendingTasks();
-}
-
-TEST_P(FileDescriptorWatcherTest, DeleteControllerAfterDeleteMessageLoopForIO) {
- auto controller = WatchReadable();
-
- // Delete the MessageLoopForIO.
- if (GetParam() ==
- FileDescriptorWatcherTestType::MESSAGE_LOOP_FOR_IO_ON_MAIN_THREAD) {
- message_loop_ = nullptr;
- } else {
- other_thread_.Stop();
- }
-
- // Deleting |controller| shouldn't crash even though that causes a task to be
- // posted to the MessageLoopForIO thread.
- controller = nullptr;
-}
-
-INSTANTIATE_TEST_CASE_P(
- MessageLoopForIOOnMainThread,
- FileDescriptorWatcherTest,
- ::testing::Values(
- FileDescriptorWatcherTestType::MESSAGE_LOOP_FOR_IO_ON_MAIN_THREAD));
-INSTANTIATE_TEST_CASE_P(
- MessageLoopForIOOnOtherThread,
- FileDescriptorWatcherTest,
- ::testing::Values(
- FileDescriptorWatcherTestType::MESSAGE_LOOP_FOR_IO_ON_OTHER_THREAD));
-
-} // namespace base
diff --git a/base/files/file_enumerator_unittest.cc b/base/files/file_enumerator_unittest.cc
deleted file mode 100644
index 11df075..0000000
--- a/base/files/file_enumerator_unittest.cc
+++ /dev/null
@@ -1,312 +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/files/file_enumerator.h"
-
-#include <utility>
-#include <vector>
-
-#include "base/containers/circular_deque.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::ElementsAre;
-using testing::IsEmpty;
-using testing::UnorderedElementsAre;
-
-namespace base {
-namespace {
-
-const FilePath::StringType kEmptyPattern;
-
-const std::vector<FileEnumerator::FolderSearchPolicy> kFolderSearchPolicies{
- FileEnumerator::FolderSearchPolicy::MATCH_ONLY,
- FileEnumerator::FolderSearchPolicy::ALL};
-
-circular_deque<FilePath> RunEnumerator(
- const FilePath& root_path,
- bool recursive,
- int file_type,
- const FilePath::StringType& pattern,
- FileEnumerator::FolderSearchPolicy folder_search_policy) {
- circular_deque<FilePath> rv;
- FileEnumerator enumerator(root_path, recursive, file_type, pattern,
- folder_search_policy);
- for (auto file = enumerator.Next(); !file.empty(); file = enumerator.Next())
- rv.emplace_back(std::move(file));
- return rv;
-}
-
-bool CreateDummyFile(const FilePath& path) {
- return WriteFile(path, "42", sizeof("42")) == sizeof("42");
-}
-
-} // namespace
-
-TEST(FileEnumerator, NotExistingPath) {
- const FilePath path = FilePath::FromUTF8Unsafe("some_not_existing_path");
- ASSERT_FALSE(PathExists(path));
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files = RunEnumerator(
- path, true, FileEnumerator::FILES & FileEnumerator::DIRECTORIES,
- FILE_PATH_LITERAL(""), policy);
- EXPECT_THAT(files, IsEmpty());
- }
-}
-
-TEST(FileEnumerator, EmptyFolder) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files =
- RunEnumerator(temp_dir.GetPath(), true,
- FileEnumerator::FILES & FileEnumerator::DIRECTORIES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, IsEmpty());
- }
-}
-
-TEST(FileEnumerator, SingleFileInFolderForFileSearch) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
- const FilePath file = path.AppendASCII("test.txt");
- ASSERT_TRUE(CreateDummyFile(file));
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files = RunEnumerator(
- temp_dir.GetPath(), true, FileEnumerator::FILES, kEmptyPattern, policy);
- EXPECT_THAT(files, ElementsAre(file));
- }
-}
-
-TEST(FileEnumerator, SingleFileInFolderForDirSearch) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
- ASSERT_TRUE(CreateDummyFile(path.AppendASCII("test.txt")));
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, IsEmpty());
- }
-}
-
-TEST(FileEnumerator, SingleFileInFolderWithFiltering) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
- const FilePath file = path.AppendASCII("test.txt");
- ASSERT_TRUE(CreateDummyFile(file));
-
- for (auto policy : kFolderSearchPolicies) {
- auto files = RunEnumerator(path, true, FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.txt"), policy);
- EXPECT_THAT(files, ElementsAre(file));
-
- files = RunEnumerator(path, true, FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.pdf"), policy);
- EXPECT_THAT(files, IsEmpty());
- }
-}
-
-TEST(FileEnumerator, TwoFilesInFolder) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
- const FilePath foo_txt = path.AppendASCII("foo.txt");
- const FilePath bar_txt = path.AppendASCII("bar.txt");
- ASSERT_TRUE(CreateDummyFile(foo_txt));
- ASSERT_TRUE(CreateDummyFile(bar_txt));
-
- for (auto policy : kFolderSearchPolicies) {
- auto files = RunEnumerator(path, true, FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.txt"), policy);
- EXPECT_THAT(files, UnorderedElementsAre(foo_txt, bar_txt));
-
- files = RunEnumerator(path, true, FileEnumerator::FILES,
- FILE_PATH_LITERAL("foo*"), policy);
- EXPECT_THAT(files, ElementsAre(foo_txt));
-
- files = RunEnumerator(path, true, FileEnumerator::FILES,
- FILE_PATH_LITERAL("*.pdf"), policy);
- EXPECT_THAT(files, IsEmpty());
-
- files =
- RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
- EXPECT_THAT(files, UnorderedElementsAre(foo_txt, bar_txt));
- }
-}
-
-TEST(FileEnumerator, SingleFolderInFolderForFileSearch) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
-
- ScopedTempDir temp_subdir;
- ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files =
- RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
- EXPECT_THAT(files, IsEmpty());
- }
-}
-
-TEST(FileEnumerator, SingleFolderInFolderForDirSearch) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
-
- ScopedTempDir temp_subdir;
- ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, ElementsAre(temp_subdir.GetPath()));
- }
-}
-
-TEST(FileEnumerator, TwoFoldersInFolder) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
-
- const FilePath subdir_foo = path.AppendASCII("foo");
- const FilePath subdir_bar = path.AppendASCII("bar");
- ASSERT_TRUE(CreateDirectory(subdir_foo));
- ASSERT_TRUE(CreateDirectory(subdir_bar));
-
- for (auto policy : kFolderSearchPolicies) {
- auto files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, UnorderedElementsAre(subdir_foo, subdir_bar));
-
- files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
- FILE_PATH_LITERAL("foo"), policy);
- EXPECT_THAT(files, ElementsAre(subdir_foo));
- }
-}
-
-TEST(FileEnumerator, FolderAndFileInFolder) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
-
- ScopedTempDir temp_subdir;
- ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
- const FilePath file = path.AppendASCII("test.txt");
- ASSERT_TRUE(CreateDummyFile(file));
-
- for (auto policy : kFolderSearchPolicies) {
- auto files =
- RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
- EXPECT_THAT(files, ElementsAre(file));
-
- files = RunEnumerator(path, true, FileEnumerator::DIRECTORIES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, ElementsAre(temp_subdir.GetPath()));
-
- files = RunEnumerator(path, true,
- FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, UnorderedElementsAre(file, temp_subdir.GetPath()));
- }
-}
-
-TEST(FileEnumerator, FilesInParentFolderAlwaysFirst) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath& path = temp_dir.GetPath();
-
- ScopedTempDir temp_subdir;
- ASSERT_TRUE(temp_subdir.CreateUniqueTempDirUnderPath(path));
- const FilePath foo_txt = path.AppendASCII("foo.txt");
- const FilePath bar_txt = temp_subdir.GetPath().AppendASCII("bar.txt");
- ASSERT_TRUE(CreateDummyFile(foo_txt));
- ASSERT_TRUE(CreateDummyFile(bar_txt));
-
- for (auto policy : kFolderSearchPolicies) {
- const auto files =
- RunEnumerator(path, true, FileEnumerator::FILES, kEmptyPattern, policy);
- EXPECT_THAT(files, ElementsAre(foo_txt, bar_txt));
- }
-}
-
-TEST(FileEnumerator, FileInSubfolder) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath subdir = temp_dir.GetPath().AppendASCII("subdir");
- ASSERT_TRUE(CreateDirectory(subdir));
-
- const FilePath file = subdir.AppendASCII("test.txt");
- ASSERT_TRUE(CreateDummyFile(file));
-
- for (auto policy : kFolderSearchPolicies) {
- auto files = RunEnumerator(temp_dir.GetPath(), true, FileEnumerator::FILES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, ElementsAre(file));
-
- files = RunEnumerator(temp_dir.GetPath(), false, FileEnumerator::FILES,
- kEmptyPattern, policy);
- EXPECT_THAT(files, IsEmpty());
- }
-}
-
-TEST(FileEnumerator, FilesInSubfoldersWithFiltering) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- const FilePath test_txt = temp_dir.GetPath().AppendASCII("test.txt");
- const FilePath subdir_foo = temp_dir.GetPath().AppendASCII("foo_subdir");
- const FilePath subdir_bar = temp_dir.GetPath().AppendASCII("bar_subdir");
- const FilePath foo_test = subdir_foo.AppendASCII("test.txt");
- const FilePath foo_foo = subdir_foo.AppendASCII("foo.txt");
- const FilePath foo_bar = subdir_foo.AppendASCII("bar.txt");
- const FilePath bar_test = subdir_bar.AppendASCII("test.txt");
- const FilePath bar_foo = subdir_bar.AppendASCII("foo.txt");
- const FilePath bar_bar = subdir_bar.AppendASCII("bar.txt");
- ASSERT_TRUE(CreateDummyFile(test_txt));
- ASSERT_TRUE(CreateDirectory(subdir_foo));
- ASSERT_TRUE(CreateDirectory(subdir_bar));
- ASSERT_TRUE(CreateDummyFile(foo_test));
- ASSERT_TRUE(CreateDummyFile(foo_foo));
- ASSERT_TRUE(CreateDummyFile(foo_bar));
- ASSERT_TRUE(CreateDummyFile(bar_test));
- ASSERT_TRUE(CreateDummyFile(bar_foo));
- ASSERT_TRUE(CreateDummyFile(bar_bar));
-
- auto files =
- RunEnumerator(temp_dir.GetPath(), true,
- FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
- FILE_PATH_LITERAL("foo*"),
- FileEnumerator::FolderSearchPolicy::MATCH_ONLY);
- EXPECT_THAT(files,
- UnorderedElementsAre(subdir_foo, foo_test, foo_foo, foo_bar));
-
- files = RunEnumerator(temp_dir.GetPath(), true,
- FileEnumerator::FILES | FileEnumerator::DIRECTORIES,
- FILE_PATH_LITERAL("foo*"),
- FileEnumerator::FolderSearchPolicy::ALL);
- EXPECT_THAT(files, UnorderedElementsAre(subdir_foo, foo_foo, bar_foo));
-}
-
-} // namespace base
diff --git a/base/files/file_locking_unittest.cc b/base/files/file_locking_unittest.cc
deleted file mode 100644
index bfe62ce..0000000
--- 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_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_unittest.cc b/base/files/file_path_unittest.cc
deleted file mode 100644
index d0fd00e..0000000
--- a/base/files/file_path_unittest.cc
+++ /dev/null
@@ -1,1319 +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 <sstream>
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-#include "base/test/scoped_locale.h"
-#endif
-
-// This macro helps avoid wrapped lines in the test structs.
-#define FPL(x) FILE_PATH_LITERAL(x)
-
-// This macro constructs strings which can contain NULs.
-#define FPS(x) FilePath::StringType(FPL(x), arraysize(FPL(x)) - 1)
-
-namespace base {
-
-struct UnaryTestData {
- const FilePath::CharType* input;
- const FilePath::CharType* expected;
-};
-
-struct UnaryBooleanTestData {
- const FilePath::CharType* input;
- bool expected;
-};
-
-struct BinaryTestData {
- const FilePath::CharType* inputs[2];
- const FilePath::CharType* expected;
-};
-
-struct BinaryBooleanTestData {
- const FilePath::CharType* inputs[2];
- bool expected;
-};
-
-struct BinaryIntTestData {
- const FilePath::CharType* inputs[2];
- int expected;
-};
-
-struct UTF8TestData {
- const FilePath::CharType* native;
- const char* utf8;
-};
-
-// file_util winds up using autoreleased objects on the Mac, so this needs
-// to be a PlatformTest
-typedef PlatformTest FilePathTest;
-
-TEST_F(FilePathTest, DirName) {
- const struct UnaryTestData cases[] = {
- { FPL(""), FPL(".") },
- { FPL("aa"), FPL(".") },
- { FPL("/aa/bb"), FPL("/aa") },
- { FPL("/aa/bb/"), FPL("/aa") },
- { FPL("/aa/bb//"), FPL("/aa") },
- { FPL("/aa/bb/ccc"), FPL("/aa/bb") },
- { FPL("/aa"), FPL("/") },
- { FPL("/aa/"), FPL("/") },
- { FPL("/"), FPL("/") },
- { FPL("//"), FPL("//") },
- { FPL("///"), FPL("/") },
- { FPL("aa/"), FPL(".") },
- { FPL("aa/bb"), FPL("aa") },
- { FPL("aa/bb/"), FPL("aa") },
- { FPL("aa/bb//"), FPL("aa") },
- { FPL("aa//bb//"), FPL("aa") },
- { FPL("aa//bb/"), FPL("aa") },
- { FPL("aa//bb"), FPL("aa") },
- { FPL("//aa/bb"), FPL("//aa") },
- { FPL("//aa/"), FPL("//") },
- { FPL("//aa"), FPL("//") },
- { FPL("0:"), FPL(".") },
- { FPL("@:"), FPL(".") },
- { FPL("[:"), FPL(".") },
- { FPL("`:"), FPL(".") },
- { FPL("{:"), FPL(".") },
- { FPL("\xB3:"), FPL(".") },
- { FPL("\xC5:"), FPL(".") },
- { FPL("/aa/../bb/cc"), FPL("/aa/../bb")},
-#if defined(OS_WIN)
- { FPL("\x0143:"), FPL(".") },
-#endif // OS_WIN
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("c:"), FPL("c:") },
- { FPL("C:"), FPL("C:") },
- { FPL("A:"), FPL("A:") },
- { FPL("Z:"), FPL("Z:") },
- { FPL("a:"), FPL("a:") },
- { FPL("z:"), FPL("z:") },
- { FPL("c:aa"), FPL("c:") },
- { FPL("c:/"), FPL("c:/") },
- { FPL("c://"), FPL("c://") },
- { FPL("c:///"), FPL("c:/") },
- { FPL("c:/aa"), FPL("c:/") },
- { FPL("c:/aa/"), FPL("c:/") },
- { FPL("c:/aa/bb"), FPL("c:/aa") },
- { FPL("c:aa/bb"), FPL("c:aa") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("\\aa\\bb"), FPL("\\aa") },
- { FPL("\\aa\\bb\\"), FPL("\\aa") },
- { FPL("\\aa\\bb\\\\"), FPL("\\aa") },
- { FPL("\\aa\\bb\\ccc"), FPL("\\aa\\bb") },
- { FPL("\\aa"), FPL("\\") },
- { FPL("\\aa\\"), FPL("\\") },
- { FPL("\\"), FPL("\\") },
- { FPL("\\\\"), FPL("\\\\") },
- { FPL("\\\\\\"), FPL("\\") },
- { FPL("aa\\"), FPL(".") },
- { FPL("aa\\bb"), FPL("aa") },
- { FPL("aa\\bb\\"), FPL("aa") },
- { FPL("aa\\bb\\\\"), FPL("aa") },
- { FPL("aa\\\\bb\\\\"), FPL("aa") },
- { FPL("aa\\\\bb\\"), FPL("aa") },
- { FPL("aa\\\\bb"), FPL("aa") },
- { FPL("\\\\aa\\bb"), FPL("\\\\aa") },
- { FPL("\\\\aa\\"), FPL("\\\\") },
- { FPL("\\\\aa"), FPL("\\\\") },
- { FPL("aa\\..\\bb\\c"), FPL("aa\\..\\bb")},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("c:\\"), FPL("c:\\") },
- { FPL("c:\\\\"), FPL("c:\\\\") },
- { FPL("c:\\\\\\"), FPL("c:\\") },
- { FPL("c:\\aa"), FPL("c:\\") },
- { FPL("c:\\aa\\"), FPL("c:\\") },
- { FPL("c:\\aa\\bb"), FPL("c:\\aa") },
- { FPL("c:aa\\bb"), FPL("c:aa") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- FilePath observed = input.DirName();
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed.value()) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-
-TEST_F(FilePathTest, BaseName) {
- const struct UnaryTestData cases[] = {
- { FPL(""), FPL("") },
- { FPL("aa"), FPL("aa") },
- { FPL("/aa/bb"), FPL("bb") },
- { FPL("/aa/bb/"), FPL("bb") },
- { FPL("/aa/bb//"), FPL("bb") },
- { FPL("/aa/bb/ccc"), FPL("ccc") },
- { FPL("/aa"), FPL("aa") },
- { FPL("/"), FPL("/") },
- { FPL("//"), FPL("//") },
- { FPL("///"), FPL("/") },
- { FPL("aa/"), FPL("aa") },
- { FPL("aa/bb"), FPL("bb") },
- { FPL("aa/bb/"), FPL("bb") },
- { FPL("aa/bb//"), FPL("bb") },
- { FPL("aa//bb//"), FPL("bb") },
- { FPL("aa//bb/"), FPL("bb") },
- { FPL("aa//bb"), FPL("bb") },
- { FPL("//aa/bb"), FPL("bb") },
- { FPL("//aa/"), FPL("aa") },
- { FPL("//aa"), FPL("aa") },
- { FPL("0:"), FPL("0:") },
- { FPL("@:"), FPL("@:") },
- { FPL("[:"), FPL("[:") },
- { FPL("`:"), FPL("`:") },
- { FPL("{:"), FPL("{:") },
- { FPL("\xB3:"), FPL("\xB3:") },
- { FPL("\xC5:"), FPL("\xC5:") },
-#if defined(OS_WIN)
- { FPL("\x0143:"), FPL("\x0143:") },
-#endif // OS_WIN
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("c:"), FPL("") },
- { FPL("C:"), FPL("") },
- { FPL("A:"), FPL("") },
- { FPL("Z:"), FPL("") },
- { FPL("a:"), FPL("") },
- { FPL("z:"), FPL("") },
- { FPL("c:aa"), FPL("aa") },
- { FPL("c:/"), FPL("/") },
- { FPL("c://"), FPL("//") },
- { FPL("c:///"), FPL("/") },
- { FPL("c:/aa"), FPL("aa") },
- { FPL("c:/aa/"), FPL("aa") },
- { FPL("c:/aa/bb"), FPL("bb") },
- { FPL("c:aa/bb"), FPL("bb") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("\\aa\\bb"), FPL("bb") },
- { FPL("\\aa\\bb\\"), FPL("bb") },
- { FPL("\\aa\\bb\\\\"), FPL("bb") },
- { FPL("\\aa\\bb\\ccc"), FPL("ccc") },
- { FPL("\\aa"), FPL("aa") },
- { FPL("\\"), FPL("\\") },
- { FPL("\\\\"), FPL("\\\\") },
- { FPL("\\\\\\"), FPL("\\") },
- { FPL("aa\\"), FPL("aa") },
- { FPL("aa\\bb"), FPL("bb") },
- { FPL("aa\\bb\\"), FPL("bb") },
- { FPL("aa\\bb\\\\"), FPL("bb") },
- { FPL("aa\\\\bb\\\\"), FPL("bb") },
- { FPL("aa\\\\bb\\"), FPL("bb") },
- { FPL("aa\\\\bb"), FPL("bb") },
- { FPL("\\\\aa\\bb"), FPL("bb") },
- { FPL("\\\\aa\\"), FPL("aa") },
- { FPL("\\\\aa"), FPL("aa") },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("c:\\"), FPL("\\") },
- { FPL("c:\\\\"), FPL("\\\\") },
- { FPL("c:\\\\\\"), FPL("\\") },
- { FPL("c:\\aa"), FPL("aa") },
- { FPL("c:\\aa\\"), FPL("aa") },
- { FPL("c:\\aa\\bb"), FPL("bb") },
- { FPL("c:aa\\bb"), FPL("bb") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- FilePath observed = input.BaseName();
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed.value()) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-
-TEST_F(FilePathTest, Append) {
- const struct BinaryTestData cases[] = {
- { { FPL(""), FPL("cc") }, FPL("cc") },
- { { FPL("."), FPL("ff") }, FPL("ff") },
- { { FPL("."), FPL("") }, FPL(".") },
- { { FPL("/"), FPL("cc") }, FPL("/cc") },
- { { FPL("/aa"), FPL("") }, FPL("/aa") },
- { { FPL("/aa/"), FPL("") }, FPL("/aa") },
- { { FPL("//aa"), FPL("") }, FPL("//aa") },
- { { FPL("//aa/"), FPL("") }, FPL("//aa") },
- { { FPL("//"), FPL("aa") }, FPL("//aa") },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:"), FPL("a") }, FPL("c:a") },
- { { FPL("c:"), FPL("") }, FPL("c:") },
- { { FPL("c:/"), FPL("a") }, FPL("c:/a") },
- { { FPL("c://"), FPL("a") }, FPL("c://a") },
- { { FPL("c:///"), FPL("a") }, FPL("c:/a") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- // Append introduces the default separator character, so these test cases
- // need to be defined with different expected results on platforms that use
- // different default separator characters.
- { { FPL("\\"), FPL("cc") }, FPL("\\cc") },
- { { FPL("\\aa"), FPL("") }, FPL("\\aa") },
- { { FPL("\\aa\\"), FPL("") }, FPL("\\aa") },
- { { FPL("\\\\aa"), FPL("") }, FPL("\\\\aa") },
- { { FPL("\\\\aa\\"), FPL("") }, FPL("\\\\aa") },
- { { FPL("\\\\"), FPL("aa") }, FPL("\\\\aa") },
- { { FPL("/aa/bb"), FPL("cc") }, FPL("/aa/bb\\cc") },
- { { FPL("/aa/bb/"), FPL("cc") }, FPL("/aa/bb\\cc") },
- { { FPL("aa/bb/"), FPL("cc") }, FPL("aa/bb\\cc") },
- { { FPL("aa/bb"), FPL("cc") }, FPL("aa/bb\\cc") },
- { { FPL("a/b"), FPL("c") }, FPL("a/b\\c") },
- { { FPL("a/b/"), FPL("c") }, FPL("a/b\\c") },
- { { FPL("//aa"), FPL("bb") }, FPL("//aa\\bb") },
- { { FPL("//aa/"), FPL("bb") }, FPL("//aa\\bb") },
- { { FPL("\\aa\\bb"), FPL("cc") }, FPL("\\aa\\bb\\cc") },
- { { FPL("\\aa\\bb\\"), FPL("cc") }, FPL("\\aa\\bb\\cc") },
- { { FPL("aa\\bb\\"), FPL("cc") }, FPL("aa\\bb\\cc") },
- { { FPL("aa\\bb"), FPL("cc") }, FPL("aa\\bb\\cc") },
- { { FPL("a\\b"), FPL("c") }, FPL("a\\b\\c") },
- { { FPL("a\\b\\"), FPL("c") }, FPL("a\\b\\c") },
- { { FPL("\\\\aa"), FPL("bb") }, FPL("\\\\aa\\bb") },
- { { FPL("\\\\aa\\"), FPL("bb") }, FPL("\\\\aa\\bb") },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:\\"), FPL("a") }, FPL("c:\\a") },
- { { FPL("c:\\\\"), FPL("a") }, FPL("c:\\\\a") },
- { { FPL("c:\\\\\\"), FPL("a") }, FPL("c:\\a") },
- { { FPL("c:\\"), FPL("") }, FPL("c:\\") },
- { { FPL("c:\\a"), FPL("b") }, FPL("c:\\a\\b") },
- { { FPL("c:\\a\\"), FPL("b") }, FPL("c:\\a\\b") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#else // FILE_PATH_USES_WIN_SEPARATORS
- { { FPL("/aa/bb"), FPL("cc") }, FPL("/aa/bb/cc") },
- { { FPL("/aa/bb/"), FPL("cc") }, FPL("/aa/bb/cc") },
- { { FPL("aa/bb/"), FPL("cc") }, FPL("aa/bb/cc") },
- { { FPL("aa/bb"), FPL("cc") }, FPL("aa/bb/cc") },
- { { FPL("a/b"), FPL("c") }, FPL("a/b/c") },
- { { FPL("a/b/"), FPL("c") }, FPL("a/b/c") },
- { { FPL("//aa"), FPL("bb") }, FPL("//aa/bb") },
- { { FPL("//aa/"), FPL("bb") }, FPL("//aa/bb") },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:/"), FPL("a") }, FPL("c:/a") },
- { { FPL("c:/"), FPL("") }, FPL("c:/") },
- { { FPL("c:/a"), FPL("b") }, FPL("c:/a/b") },
- { { FPL("c:/a/"), FPL("b") }, FPL("c:/a/b") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath root(cases[i].inputs[0]);
- FilePath::StringType leaf(cases[i].inputs[1]);
- FilePath observed_str = root.Append(leaf);
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed_str.value()) <<
- "i: " << i << ", root: " << root.value() << ", leaf: " << leaf;
- FilePath observed_path = root.Append(FilePath(leaf));
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed_path.value()) <<
- "i: " << i << ", root: " << root.value() << ", leaf: " << leaf;
-
- // TODO(erikkay): It would be nice to have a unicode test append value to
- // handle the case when AppendASCII is passed UTF8
-#if defined(OS_WIN)
- std::string ascii = WideToUTF8(leaf);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- std::string ascii = leaf;
-#endif
- observed_str = root.AppendASCII(ascii);
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed_str.value()) <<
- "i: " << i << ", root: " << root.value() << ", leaf: " << leaf;
- }
-}
-
-TEST_F(FilePathTest, StripTrailingSeparators) {
- const struct UnaryTestData cases[] = {
- { FPL(""), FPL("") },
- { FPL("/"), FPL("/") },
- { FPL("//"), FPL("//") },
- { FPL("///"), FPL("/") },
- { FPL("////"), FPL("/") },
- { FPL("a/"), FPL("a") },
- { FPL("a//"), FPL("a") },
- { FPL("a///"), FPL("a") },
- { FPL("a////"), FPL("a") },
- { FPL("/a"), FPL("/a") },
- { FPL("/a/"), FPL("/a") },
- { FPL("/a//"), FPL("/a") },
- { FPL("/a///"), FPL("/a") },
- { FPL("/a////"), FPL("/a") },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("c:"), FPL("c:") },
- { FPL("c:/"), FPL("c:/") },
- { FPL("c://"), FPL("c://") },
- { FPL("c:///"), FPL("c:/") },
- { FPL("c:////"), FPL("c:/") },
- { FPL("c:/a"), FPL("c:/a") },
- { FPL("c:/a/"), FPL("c:/a") },
- { FPL("c:/a//"), FPL("c:/a") },
- { FPL("c:/a///"), FPL("c:/a") },
- { FPL("c:/a////"), FPL("c:/a") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("\\"), FPL("\\") },
- { FPL("\\\\"), FPL("\\\\") },
- { FPL("\\\\\\"), FPL("\\") },
- { FPL("\\\\\\\\"), FPL("\\") },
- { FPL("a\\"), FPL("a") },
- { FPL("a\\\\"), FPL("a") },
- { FPL("a\\\\\\"), FPL("a") },
- { FPL("a\\\\\\\\"), FPL("a") },
- { FPL("\\a"), FPL("\\a") },
- { FPL("\\a\\"), FPL("\\a") },
- { FPL("\\a\\\\"), FPL("\\a") },
- { FPL("\\a\\\\\\"), FPL("\\a") },
- { FPL("\\a\\\\\\\\"), FPL("\\a") },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("c:\\"), FPL("c:\\") },
- { FPL("c:\\\\"), FPL("c:\\\\") },
- { FPL("c:\\\\\\"), FPL("c:\\") },
- { FPL("c:\\\\\\\\"), FPL("c:\\") },
- { FPL("c:\\a"), FPL("c:\\a") },
- { FPL("c:\\a\\"), FPL("c:\\a") },
- { FPL("c:\\a\\\\"), FPL("c:\\a") },
- { FPL("c:\\a\\\\\\"), FPL("c:\\a") },
- { FPL("c:\\a\\\\\\\\"), FPL("c:\\a") },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- FilePath observed = input.StripTrailingSeparators();
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed.value()) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-
-TEST_F(FilePathTest, IsAbsolute) {
- const struct UnaryBooleanTestData cases[] = {
- { FPL(""), false },
- { FPL("a"), false },
- { FPL("c:"), false },
- { FPL("c:a"), false },
- { FPL("a/b"), false },
- { FPL("//"), true },
- { FPL("//a"), true },
- { FPL("c:a/b"), false },
- { FPL("?:/a"), false },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("/"), false },
- { FPL("/a"), false },
- { FPL("/."), false },
- { FPL("/.."), false },
- { FPL("c:/"), true },
- { FPL("c:/a"), true },
- { FPL("c:/."), true },
- { FPL("c:/.."), true },
- { FPL("C:/a"), true },
- { FPL("d:/a"), true },
-#else // FILE_PATH_USES_DRIVE_LETTERS
- { FPL("/"), true },
- { FPL("/a"), true },
- { FPL("/."), true },
- { FPL("/.."), true },
- { FPL("c:/"), false },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("a\\b"), false },
- { FPL("\\\\"), true },
- { FPL("\\\\a"), true },
- { FPL("a\\b"), false },
- { FPL("\\\\"), true },
- { FPL("//a"), true },
- { FPL("c:a\\b"), false },
- { FPL("?:\\a"), false },
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("\\"), false },
- { FPL("\\a"), false },
- { FPL("\\."), false },
- { FPL("\\.."), false },
- { FPL("c:\\"), true },
- { FPL("c:\\"), true },
- { FPL("c:\\a"), true },
- { FPL("c:\\."), true },
- { FPL("c:\\.."), true },
- { FPL("C:\\a"), true },
- { FPL("d:\\a"), true },
-#else // FILE_PATH_USES_DRIVE_LETTERS
- { FPL("\\"), true },
- { FPL("\\a"), true },
- { FPL("\\."), true },
- { FPL("\\.."), true },
- { FPL("c:\\"), false },
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- bool observed = input.IsAbsolute();
- EXPECT_EQ(cases[i].expected, observed) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-
-TEST_F(FilePathTest, PathComponentsTest) {
- const struct UnaryTestData cases[] = {
- { FPL("//foo/bar/baz/"), FPL("|//|foo|bar|baz")},
- { FPL("///"), FPL("|/")},
- { FPL("/foo//bar//baz/"), FPL("|/|foo|bar|baz")},
- { FPL("/foo/bar/baz/"), FPL("|/|foo|bar|baz")},
- { FPL("/foo/bar/baz//"), FPL("|/|foo|bar|baz")},
- { FPL("/foo/bar/baz///"), FPL("|/|foo|bar|baz")},
- { FPL("/foo/bar/baz"), FPL("|/|foo|bar|baz")},
- { FPL("/foo/bar.bot/baz.txt"), FPL("|/|foo|bar.bot|baz.txt")},
- { FPL("//foo//bar/baz"), FPL("|//|foo|bar|baz")},
- { FPL("/"), FPL("|/")},
- { FPL("foo"), FPL("|foo")},
- { FPL(""), FPL("")},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { FPL("e:/foo"), FPL("|e:|/|foo")},
- { FPL("e:/"), FPL("|e:|/")},
- { FPL("e:"), FPL("|e:")},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("../foo"), FPL("|..|foo")},
- { FPL("./foo"), FPL("|foo")},
- { FPL("../foo/bar/"), FPL("|..|foo|bar") },
- { FPL("\\\\foo\\bar\\baz\\"), FPL("|\\\\|foo|bar|baz")},
- { FPL("\\\\\\"), FPL("|\\")},
- { FPL("\\foo\\\\bar\\\\baz\\"), FPL("|\\|foo|bar|baz")},
- { FPL("\\foo\\bar\\baz\\"), FPL("|\\|foo|bar|baz")},
- { FPL("\\foo\\bar\\baz\\\\"), FPL("|\\|foo|bar|baz")},
- { FPL("\\foo\\bar\\baz\\\\\\"), FPL("|\\|foo|bar|baz")},
- { FPL("\\foo\\bar\\baz"), FPL("|\\|foo|bar|baz")},
- { FPL("\\foo\\bar/baz\\\\\\"), FPL("|\\|foo|bar|baz")},
- { FPL("/foo\\bar\\baz"), FPL("|/|foo|bar|baz")},
- { FPL("\\foo\\bar.bot\\baz.txt"), FPL("|\\|foo|bar.bot|baz.txt")},
- { FPL("\\\\foo\\\\bar\\baz"), FPL("|\\\\|foo|bar|baz")},
- { FPL("\\"), FPL("|\\")},
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- std::vector<FilePath::StringType> comps;
- input.GetComponents(&comps);
-
- FilePath::StringType observed;
- for (size_t j = 0; j < comps.size(); ++j) {
- observed.append(FILE_PATH_LITERAL("|"), 1);
- observed.append(comps[j]);
- }
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-
-TEST_F(FilePathTest, IsParentTest) {
- const struct BinaryBooleanTestData cases[] = {
- { { FPL("/"), FPL("/foo/bar/baz") }, true},
- { { FPL("/foo/bar"), FPL("/foo/bar/baz") }, true},
- { { FPL("/foo/bar/"), FPL("/foo/bar/baz") }, true},
- { { FPL("//foo/bar/"), FPL("//foo/bar/baz") }, true},
- { { FPL("/foo/bar"), FPL("/foo2/bar/baz") }, false},
- { { FPL("/foo/bar.txt"), FPL("/foo/bar/baz") }, false},
- { { FPL("/foo/bar"), FPL("/foo/bar2/baz") }, false},
- { { FPL("/foo/bar"), FPL("/foo/bar") }, false},
- { { FPL("/foo/bar/baz"), FPL("/foo/bar") }, false},
- { { FPL("foo/bar"), FPL("foo/bar/baz") }, true},
- { { FPL("foo/bar"), FPL("foo2/bar/baz") }, false},
- { { FPL("foo/bar"), FPL("foo/bar2/baz") }, false},
- { { FPL(""), FPL("foo") }, false},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:/foo/bar"), FPL("c:/foo/bar/baz") }, true},
- { { FPL("E:/foo/bar"), FPL("e:/foo/bar/baz") }, true},
- { { FPL("f:/foo/bar"), FPL("F:/foo/bar/baz") }, true},
- { { FPL("E:/Foo/bar"), FPL("e:/foo/bar/baz") }, false},
- { { FPL("f:/foo/bar"), FPL("F:/foo/Bar/baz") }, false},
- { { FPL("c:/"), FPL("c:/foo/bar/baz") }, true},
- { { FPL("c:"), FPL("c:/foo/bar/baz") }, true},
- { { FPL("c:/foo/bar"), FPL("d:/foo/bar/baz") }, false},
- { { FPL("c:/foo/bar"), FPL("D:/foo/bar/baz") }, false},
- { { FPL("C:/foo/bar"), FPL("d:/foo/bar/baz") }, false},
- { { FPL("c:/foo/bar"), FPL("c:/foo2/bar/baz") }, false},
- { { FPL("e:/foo/bar"), FPL("E:/foo2/bar/baz") }, false},
- { { FPL("F:/foo/bar"), FPL("f:/foo2/bar/baz") }, false},
- { { FPL("c:/foo/bar"), FPL("c:/foo/bar2/baz") }, false},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("\\foo\\bar"), FPL("\\foo\\bar\\baz") }, true},
- { { FPL("\\foo/bar"), FPL("\\foo\\bar\\baz") }, true},
- { { FPL("\\foo/bar"), FPL("\\foo/bar/baz") }, true},
- { { FPL("\\"), FPL("\\foo\\bar\\baz") }, true},
- { { FPL(""), FPL("\\foo\\bar\\baz") }, false},
- { { FPL("\\foo\\bar"), FPL("\\foo2\\bar\\baz") }, false},
- { { FPL("\\foo\\bar"), FPL("\\foo\\bar2\\baz") }, false},
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath parent(cases[i].inputs[0]);
- FilePath child(cases[i].inputs[1]);
-
- EXPECT_EQ(parent.IsParent(child), cases[i].expected) <<
- "i: " << i << ", parent: " << parent.value() << ", child: " <<
- child.value();
- }
-}
-
-TEST_F(FilePathTest, AppendRelativePathTest) {
- const struct BinaryTestData cases[] = {
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("/"), FPL("/foo/bar/baz") }, FPL("foo\\bar\\baz")},
-#else // FILE_PATH_USES_WIN_SEPARATORS
- { { FPL("/"), FPL("/foo/bar/baz") }, FPL("foo/bar/baz")},
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- { { FPL("/foo/bar"), FPL("/foo/bar/baz") }, FPL("baz")},
- { { FPL("/foo/bar/"), FPL("/foo/bar/baz") }, FPL("baz")},
- { { FPL("//foo/bar/"), FPL("//foo/bar/baz") }, FPL("baz")},
- { { FPL("/foo/bar"), FPL("/foo2/bar/baz") }, FPL("")},
- { { FPL("/foo/bar.txt"), FPL("/foo/bar/baz") }, FPL("")},
- { { FPL("/foo/bar"), FPL("/foo/bar2/baz") }, FPL("")},
- { { FPL("/foo/bar"), FPL("/foo/bar") }, FPL("")},
- { { FPL("/foo/bar/baz"), FPL("/foo/bar") }, FPL("")},
- { { FPL("foo/bar"), FPL("foo/bar/baz") }, FPL("baz")},
- { { FPL("foo/bar"), FPL("foo2/bar/baz") }, FPL("")},
- { { FPL("foo/bar"), FPL("foo/bar2/baz") }, FPL("")},
- { { FPL(""), FPL("foo") }, FPL("")},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:/foo/bar"), FPL("c:/foo/bar/baz") }, FPL("baz")},
- { { FPL("E:/foo/bar"), FPL("e:/foo/bar/baz") }, FPL("baz")},
- { { FPL("f:/foo/bar"), FPL("F:/foo/bar/baz") }, FPL("baz")},
- { { FPL("E:/Foo/bar"), FPL("e:/foo/bar/baz") }, FPL("")},
- { { FPL("f:/foo/bar"), FPL("F:/foo/Bar/baz") }, FPL("")},
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("c:/"), FPL("c:/foo/bar/baz") }, FPL("foo\\bar\\baz")},
- // TODO(akalin): Figure out how to handle the corner case in the
- // commented-out test case below. Appending to an empty path gives
- // /foo\bar\baz but appending to a nonempty path "blah" gives
- // blah\foo\bar\baz.
- // { { FPL("c:"), FPL("c:/foo/bar/baz") }, FPL("foo\\bar\\baz")},
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- { { FPL("c:/foo/bar"), FPL("d:/foo/bar/baz") }, FPL("")},
- { { FPL("c:/foo/bar"), FPL("D:/foo/bar/baz") }, FPL("")},
- { { FPL("C:/foo/bar"), FPL("d:/foo/bar/baz") }, FPL("")},
- { { FPL("c:/foo/bar"), FPL("c:/foo2/bar/baz") }, FPL("")},
- { { FPL("e:/foo/bar"), FPL("E:/foo2/bar/baz") }, FPL("")},
- { { FPL("F:/foo/bar"), FPL("f:/foo2/bar/baz") }, FPL("")},
- { { FPL("c:/foo/bar"), FPL("c:/foo/bar2/baz") }, FPL("")},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("\\foo\\bar"), FPL("\\foo\\bar\\baz") }, FPL("baz")},
- { { FPL("\\foo/bar"), FPL("\\foo\\bar\\baz") }, FPL("baz")},
- { { FPL("\\foo/bar"), FPL("\\foo/bar/baz") }, FPL("baz")},
- { { FPL("\\"), FPL("\\foo\\bar\\baz") }, FPL("foo\\bar\\baz")},
- { { FPL(""), FPL("\\foo\\bar\\baz") }, FPL("")},
- { { FPL("\\foo\\bar"), FPL("\\foo2\\bar\\baz") }, FPL("")},
- { { FPL("\\foo\\bar"), FPL("\\foo\\bar2\\baz") }, FPL("")},
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- const FilePath base(FPL("blah"));
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath parent(cases[i].inputs[0]);
- FilePath child(cases[i].inputs[1]);
- {
- FilePath result;
- bool success = parent.AppendRelativePath(child, &result);
- EXPECT_EQ(cases[i].expected[0] != '\0', success) <<
- "i: " << i << ", parent: " << parent.value() << ", child: " <<
- child.value();
- EXPECT_STREQ(cases[i].expected, result.value().c_str()) <<
- "i: " << i << ", parent: " << parent.value() << ", child: " <<
- child.value();
- }
- {
- FilePath result(base);
- bool success = parent.AppendRelativePath(child, &result);
- EXPECT_EQ(cases[i].expected[0] != '\0', success) <<
- "i: " << i << ", parent: " << parent.value() << ", child: " <<
- child.value();
- EXPECT_EQ(base.Append(cases[i].expected).value(), result.value()) <<
- "i: " << i << ", parent: " << parent.value() << ", child: " <<
- child.value();
- }
- }
-}
-
-TEST_F(FilePathTest, EqualityTest) {
- const struct BinaryBooleanTestData cases[] = {
- { { FPL("/foo/bar/baz"), FPL("/foo/bar/baz") }, true},
- { { FPL("/foo/bar"), FPL("/foo/bar/baz") }, false},
- { { FPL("/foo/bar/baz"), FPL("/foo/bar") }, false},
- { { FPL("//foo/bar/"), FPL("//foo/bar/") }, true},
- { { FPL("/foo/bar"), FPL("/foo2/bar") }, false},
- { { FPL("/foo/bar.txt"), FPL("/foo/bar") }, false},
- { { FPL("foo/bar"), FPL("foo/bar") }, true},
- { { FPL("foo/bar"), FPL("foo/bar/baz") }, false},
- { { FPL(""), FPL("foo") }, false},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:/foo/bar"), FPL("c:/foo/bar") }, true},
- { { FPL("E:/foo/bar"), FPL("e:/foo/bar") }, true},
- { { FPL("f:/foo/bar"), FPL("F:/foo/bar") }, true},
- { { FPL("E:/Foo/bar"), FPL("e:/foo/bar") }, false},
- { { FPL("f:/foo/bar"), FPL("F:/foo/Bar") }, false},
- { { FPL("c:/"), FPL("c:/") }, true},
- { { FPL("c:"), FPL("c:") }, true},
- { { FPL("c:/foo/bar"), FPL("d:/foo/bar") }, false},
- { { FPL("c:/foo/bar"), FPL("D:/foo/bar") }, false},
- { { FPL("C:/foo/bar"), FPL("d:/foo/bar") }, false},
- { { FPL("c:/foo/bar"), FPL("c:/foo2/bar") }, false},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("\\foo\\bar"), FPL("\\foo\\bar") }, true},
- { { FPL("\\foo/bar"), FPL("\\foo/bar") }, true},
- { { FPL("\\foo/bar"), FPL("\\foo\\bar") }, false},
- { { FPL("\\"), FPL("\\") }, true},
- { { FPL("\\"), FPL("/") }, false},
- { { FPL(""), FPL("\\") }, false},
- { { FPL("\\foo\\bar"), FPL("\\foo2\\bar") }, false},
- { { FPL("\\foo\\bar"), FPL("\\foo\\bar2") }, false},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:\\foo\\bar"), FPL("c:\\foo\\bar") }, true},
- { { FPL("E:\\foo\\bar"), FPL("e:\\foo\\bar") }, true},
- { { FPL("f:\\foo\\bar"), FPL("F:\\foo/bar") }, false},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#endif // FILE_PATH_USES_WIN_SEPARATORS
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath a(cases[i].inputs[0]);
- FilePath b(cases[i].inputs[1]);
-
- EXPECT_EQ(a == b, cases[i].expected) <<
- "equality i: " << i << ", a: " << a.value() << ", b: " <<
- b.value();
- }
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath a(cases[i].inputs[0]);
- FilePath b(cases[i].inputs[1]);
-
- EXPECT_EQ(a != b, !cases[i].expected) <<
- "inequality i: " << i << ", a: " << a.value() << ", b: " <<
- b.value();
- }
-}
-
-TEST_F(FilePathTest, Extension) {
- FilePath base_dir(FILE_PATH_LITERAL("base_dir"));
-
- FilePath jpg = base_dir.Append(FILE_PATH_LITERAL("foo.jpg"));
- EXPECT_EQ(FILE_PATH_LITERAL(".jpg"), jpg.Extension());
- EXPECT_EQ(FILE_PATH_LITERAL(".jpg"), jpg.FinalExtension());
-
- FilePath base = jpg.BaseName().RemoveExtension();
- EXPECT_EQ(FILE_PATH_LITERAL("foo"), base.value());
-
- FilePath path_no_ext = base_dir.Append(base);
- EXPECT_EQ(path_no_ext.value(), jpg.RemoveExtension().value());
-
- EXPECT_EQ(path_no_ext.value(), path_no_ext.RemoveExtension().value());
- EXPECT_EQ(FILE_PATH_LITERAL(""), path_no_ext.Extension());
- EXPECT_EQ(FILE_PATH_LITERAL(""), path_no_ext.FinalExtension());
-}
-
-TEST_F(FilePathTest, Extension2) {
- const struct UnaryTestData cases[] = {
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("C:\\a\\b\\c.ext"), FPL(".ext") },
- { FPL("C:\\a\\b\\c."), FPL(".") },
- { FPL("C:\\a\\b\\c"), FPL("") },
- { FPL("C:\\a\\b\\"), FPL("") },
- { FPL("C:\\a\\b.\\"), FPL(".") },
- { FPL("C:\\a\\b\\c.ext1.ext2"), FPL(".ext2") },
- { FPL("C:\\foo.bar\\\\\\"), FPL(".bar") },
- { FPL("C:\\foo.bar\\.."), FPL("") },
- { FPL("C:\\foo.bar\\..\\\\"), FPL("") },
-#endif
- { FPL("/foo/bar/baz.ext"), FPL(".ext") },
- { FPL("/foo/bar/baz."), FPL(".") },
- { FPL("/foo/bar/baz.."), FPL(".") },
- { FPL("/foo/bar/baz"), FPL("") },
- { FPL("/foo/bar/"), FPL("") },
- { FPL("/foo/bar./"), FPL(".") },
- { FPL("/foo/bar/baz.ext1.ext2"), FPL(".ext2") },
- { FPL("/subversion-1.6.12.zip"), FPL(".zip") },
- { FPL("/foo.12345.gz"), FPL(".gz") },
- { FPL("/foo..gz"), FPL(".gz") },
- { FPL("."), FPL("") },
- { FPL(".."), FPL("") },
- { FPL("./foo"), FPL("") },
- { FPL("./foo.ext"), FPL(".ext") },
- { FPL("/foo.ext1/bar.ext2"), FPL(".ext2") },
- { FPL("/foo.bar////"), FPL(".bar") },
- { FPL("/foo.bar/.."), FPL("") },
- { FPL("/foo.bar/..////"), FPL("") },
- { FPL("/foo.1234.luser.js"), FPL(".js") },
- { FPL("/user.js"), FPL(".js") },
- };
- const struct UnaryTestData double_extension_cases[] = {
- { FPL("/foo.tar.gz"), FPL(".tar.gz") },
- { FPL("/foo.tar.Z"), FPL(".tar.Z") },
- { FPL("/foo.tar.bz2"), FPL(".tar.bz2") },
- { FPL("/foo.1234.gz"), FPL(".1234.gz") },
- { FPL("/foo.1234.tar.gz"), FPL(".tar.gz") },
- { FPL("/foo.tar.tar.gz"), FPL(".tar.gz") },
- { FPL("/foo.tar.gz.gz"), FPL(".gz.gz") },
- { FPL("/foo.1234.user.js"), FPL(".user.js") },
- { FPL("foo.user.js"), FPL(".user.js") },
- { FPL("/foo.tar.bz"), FPL(".tar.bz") },
- };
- for (unsigned int i = 0; i < arraysize(cases); ++i) {
- FilePath path(cases[i].input);
- FilePath::StringType extension = path.Extension();
- FilePath::StringType final_extension = path.FinalExtension();
- EXPECT_STREQ(cases[i].expected, extension.c_str())
- << "i: " << i << ", path: " << path.value();
- EXPECT_STREQ(cases[i].expected, final_extension.c_str())
- << "i: " << i << ", path: " << path.value();
- }
- for (unsigned int i = 0; i < arraysize(double_extension_cases); ++i) {
- FilePath path(double_extension_cases[i].input);
- FilePath::StringType extension = path.Extension();
- EXPECT_STREQ(double_extension_cases[i].expected, extension.c_str())
- << "i: " << i << ", path: " << path.value();
- }
-}
-
-TEST_F(FilePathTest, InsertBeforeExtension) {
- const struct BinaryTestData cases[] = {
- { { FPL(""), FPL("") }, FPL("") },
- { { FPL(""), FPL("txt") }, FPL("") },
- { { FPL("."), FPL("txt") }, FPL("") },
- { { FPL(".."), FPL("txt") }, FPL("") },
- { { FPL("foo.dll"), FPL("txt") }, FPL("footxt.dll") },
- { { FPL("."), FPL("") }, FPL(".") },
- { { FPL("foo.dll"), FPL(".txt") }, FPL("foo.txt.dll") },
- { { FPL("foo"), FPL("txt") }, FPL("footxt") },
- { { FPL("foo"), FPL(".txt") }, FPL("foo.txt") },
- { { FPL("foo.baz.dll"), FPL("txt") }, FPL("foo.baztxt.dll") },
- { { FPL("foo.baz.dll"), FPL(".txt") }, FPL("foo.baz.txt.dll") },
- { { FPL("foo.dll"), FPL("") }, FPL("foo.dll") },
- { { FPL("foo.dll"), FPL(".") }, FPL("foo..dll") },
- { { FPL("foo"), FPL("") }, FPL("foo") },
- { { FPL("foo"), FPL(".") }, FPL("foo.") },
- { { FPL("foo.baz.dll"), FPL("") }, FPL("foo.baz.dll") },
- { { FPL("foo.baz.dll"), FPL(".") }, FPL("foo.baz..dll") },
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("\\"), FPL("") }, FPL("\\") },
- { { FPL("\\"), FPL("txt") }, FPL("\\txt") },
- { { FPL("\\."), FPL("txt") }, FPL("") },
- { { FPL("\\.."), FPL("txt") }, FPL("") },
- { { FPL("\\."), FPL("") }, FPL("\\.") },
- { { FPL("C:\\bar\\foo.dll"), FPL("txt") },
- FPL("C:\\bar\\footxt.dll") },
- { { FPL("C:\\bar.baz\\foodll"), FPL("txt") },
- FPL("C:\\bar.baz\\foodlltxt") },
- { { FPL("C:\\bar.baz\\foo.dll"), FPL("txt") },
- FPL("C:\\bar.baz\\footxt.dll") },
- { { FPL("C:\\bar.baz\\foo.dll.exe"), FPL("txt") },
- FPL("C:\\bar.baz\\foo.dlltxt.exe") },
- { { FPL("C:\\bar.baz\\foo"), FPL("") },
- FPL("C:\\bar.baz\\foo") },
- { { FPL("C:\\bar.baz\\foo.exe"), FPL("") },
- FPL("C:\\bar.baz\\foo.exe") },
- { { FPL("C:\\bar.baz\\foo.dll.exe"), FPL("") },
- FPL("C:\\bar.baz\\foo.dll.exe") },
- { { FPL("C:\\bar\\baz\\foo.exe"), FPL(" (1)") },
- FPL("C:\\bar\\baz\\foo (1).exe") },
- { { FPL("C:\\foo.baz\\\\"), FPL(" (1)") }, FPL("C:\\foo (1).baz") },
- { { FPL("C:\\foo.baz\\..\\"), FPL(" (1)") }, FPL("") },
-#endif
- { { FPL("/"), FPL("") }, FPL("/") },
- { { FPL("/"), FPL("txt") }, FPL("/txt") },
- { { FPL("/."), FPL("txt") }, FPL("") },
- { { FPL("/.."), FPL("txt") }, FPL("") },
- { { FPL("/."), FPL("") }, FPL("/.") },
- { { FPL("/bar/foo.dll"), FPL("txt") }, FPL("/bar/footxt.dll") },
- { { FPL("/bar.baz/foodll"), FPL("txt") }, FPL("/bar.baz/foodlltxt") },
- { { FPL("/bar.baz/foo.dll"), FPL("txt") }, FPL("/bar.baz/footxt.dll") },
- { { FPL("/bar.baz/foo.dll.exe"), FPL("txt") },
- FPL("/bar.baz/foo.dlltxt.exe") },
- { { FPL("/bar.baz/foo"), FPL("") }, FPL("/bar.baz/foo") },
- { { FPL("/bar.baz/foo.exe"), FPL("") }, FPL("/bar.baz/foo.exe") },
- { { FPL("/bar.baz/foo.dll.exe"), FPL("") }, FPL("/bar.baz/foo.dll.exe") },
- { { FPL("/bar/baz/foo.exe"), FPL(" (1)") }, FPL("/bar/baz/foo (1).exe") },
- { { FPL("/bar/baz/..////"), FPL(" (1)") }, FPL("") },
- };
- for (unsigned int i = 0; i < arraysize(cases); ++i) {
- FilePath path(cases[i].inputs[0]);
- FilePath result = path.InsertBeforeExtension(cases[i].inputs[1]);
- EXPECT_EQ(cases[i].expected, result.value()) << "i: " << i <<
- ", path: " << path.value() << ", insert: " << cases[i].inputs[1];
- }
-}
-
-TEST_F(FilePathTest, RemoveExtension) {
- const struct UnaryTestData cases[] = {
- { FPL(""), FPL("") },
- { FPL("."), FPL(".") },
- { FPL(".."), FPL("..") },
- { FPL("foo.dll"), FPL("foo") },
- { FPL("./foo.dll"), FPL("./foo") },
- { FPL("foo..dll"), FPL("foo.") },
- { FPL("foo"), FPL("foo") },
- { FPL("foo."), FPL("foo") },
- { FPL("foo.."), FPL("foo.") },
- { FPL("foo.baz.dll"), FPL("foo.baz") },
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { FPL("C:\\foo.bar\\foo"), FPL("C:\\foo.bar\\foo") },
- { FPL("C:\\foo.bar\\..\\\\"), FPL("C:\\foo.bar\\..\\\\") },
-#endif
- { FPL("/foo.bar/foo"), FPL("/foo.bar/foo") },
- { FPL("/foo.bar/..////"), FPL("/foo.bar/..////") },
- };
- for (unsigned int i = 0; i < arraysize(cases); ++i) {
- FilePath path(cases[i].input);
- FilePath removed = path.RemoveExtension();
- FilePath removed_final = path.RemoveFinalExtension();
- EXPECT_EQ(cases[i].expected, removed.value()) << "i: " << i <<
- ", path: " << path.value();
- EXPECT_EQ(cases[i].expected, removed_final.value()) << "i: " << i <<
- ", path: " << path.value();
- }
- {
- FilePath path(FPL("foo.tar.gz"));
- FilePath removed = path.RemoveExtension();
- FilePath removed_final = path.RemoveFinalExtension();
- EXPECT_EQ(FPL("foo"), removed.value()) << ", path: " << path.value();
- EXPECT_EQ(FPL("foo.tar"), removed_final.value()) << ", path: "
- << path.value();
- }
-}
-
-TEST_F(FilePathTest, ReplaceExtension) {
- const struct BinaryTestData cases[] = {
- { { FPL(""), FPL("") }, FPL("") },
- { { FPL(""), FPL("txt") }, FPL("") },
- { { FPL("."), FPL("txt") }, FPL("") },
- { { FPL(".."), FPL("txt") }, FPL("") },
- { { FPL("."), FPL("") }, FPL("") },
- { { FPL("foo.dll"), FPL("txt") }, FPL("foo.txt") },
- { { FPL("./foo.dll"), FPL("txt") }, FPL("./foo.txt") },
- { { FPL("foo..dll"), FPL("txt") }, FPL("foo..txt") },
- { { FPL("foo.dll"), FPL(".txt") }, FPL("foo.txt") },
- { { FPL("foo"), FPL("txt") }, FPL("foo.txt") },
- { { FPL("foo."), FPL("txt") }, FPL("foo.txt") },
- { { FPL("foo.."), FPL("txt") }, FPL("foo..txt") },
- { { FPL("foo"), FPL(".txt") }, FPL("foo.txt") },
- { { FPL("foo.baz.dll"), FPL("txt") }, FPL("foo.baz.txt") },
- { { FPL("foo.baz.dll"), FPL(".txt") }, FPL("foo.baz.txt") },
- { { FPL("foo.dll"), FPL("") }, FPL("foo") },
- { { FPL("foo.dll"), FPL(".") }, FPL("foo") },
- { { FPL("foo"), FPL("") }, FPL("foo") },
- { { FPL("foo"), FPL(".") }, FPL("foo") },
- { { FPL("foo.baz.dll"), FPL("") }, FPL("foo.baz") },
- { { FPL("foo.baz.dll"), FPL(".") }, FPL("foo.baz") },
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("C:\\foo.bar\\foo"), FPL("baz") }, FPL("C:\\foo.bar\\foo.baz") },
- { { FPL("C:\\foo.bar\\..\\\\"), FPL("baz") }, FPL("") },
-#endif
- { { FPL("/foo.bar/foo"), FPL("baz") }, FPL("/foo.bar/foo.baz") },
- { { FPL("/foo.bar/..////"), FPL("baz") }, FPL("") },
- };
- for (unsigned int i = 0; i < arraysize(cases); ++i) {
- FilePath path(cases[i].inputs[0]);
- FilePath replaced = path.ReplaceExtension(cases[i].inputs[1]);
- EXPECT_EQ(cases[i].expected, replaced.value()) << "i: " << i <<
- ", path: " << path.value() << ", replace: " << cases[i].inputs[1];
- }
-}
-
-TEST_F(FilePathTest, AddExtension) {
- const struct BinaryTestData cases[] = {
- { { FPL(""), FPL("") }, FPL("") },
- { { FPL(""), FPL("txt") }, FPL("") },
- { { FPL("."), FPL("txt") }, FPL("") },
- { { FPL(".."), FPL("txt") }, FPL("") },
- { { FPL("."), FPL("") }, FPL("") },
- { { FPL("foo.dll"), FPL("txt") }, FPL("foo.dll.txt") },
- { { FPL("./foo.dll"), FPL("txt") }, FPL("./foo.dll.txt") },
- { { FPL("foo..dll"), FPL("txt") }, FPL("foo..dll.txt") },
- { { FPL("foo.dll"), FPL(".txt") }, FPL("foo.dll.txt") },
- { { FPL("foo"), FPL("txt") }, FPL("foo.txt") },
- { { FPL("foo."), FPL("txt") }, FPL("foo.txt") },
- { { FPL("foo.."), FPL("txt") }, FPL("foo..txt") },
- { { FPL("foo"), FPL(".txt") }, FPL("foo.txt") },
- { { FPL("foo.baz.dll"), FPL("txt") }, FPL("foo.baz.dll.txt") },
- { { FPL("foo.baz.dll"), FPL(".txt") }, FPL("foo.baz.dll.txt") },
- { { FPL("foo.dll"), FPL("") }, FPL("foo.dll") },
- { { FPL("foo.dll"), FPL(".") }, FPL("foo.dll") },
- { { FPL("foo"), FPL("") }, FPL("foo") },
- { { FPL("foo"), FPL(".") }, FPL("foo") },
- { { FPL("foo.baz.dll"), FPL("") }, FPL("foo.baz.dll") },
- { { FPL("foo.baz.dll"), FPL(".") }, FPL("foo.baz.dll") },
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("C:\\foo.bar\\foo"), FPL("baz") }, FPL("C:\\foo.bar\\foo.baz") },
- { { FPL("C:\\foo.bar\\..\\\\"), FPL("baz") }, FPL("") },
-#endif
- { { FPL("/foo.bar/foo"), FPL("baz") }, FPL("/foo.bar/foo.baz") },
- { { FPL("/foo.bar/..////"), FPL("baz") }, FPL("") },
- };
- for (unsigned int i = 0; i < arraysize(cases); ++i) {
- FilePath path(cases[i].inputs[0]);
- FilePath added = path.AddExtension(cases[i].inputs[1]);
- EXPECT_EQ(cases[i].expected, added.value()) << "i: " << i <<
- ", path: " << path.value() << ", add: " << cases[i].inputs[1];
- }
-}
-
-TEST_F(FilePathTest, MatchesExtension) {
- const struct BinaryBooleanTestData cases[] = {
- { { FPL("foo"), FPL("") }, true},
- { { FPL("foo"), FPL(".") }, false},
- { { FPL("foo."), FPL("") }, false},
- { { FPL("foo."), FPL(".") }, true},
- { { FPL("foo.txt"), FPL(".dll") }, false},
- { { FPL("foo.txt"), FPL(".txt") }, true},
- { { FPL("foo.txt.dll"), FPL(".txt") }, false},
- { { FPL("foo.txt.dll"), FPL(".dll") }, true},
- { { FPL("foo.TXT"), FPL(".txt") }, true},
- { { FPL("foo.txt"), FPL(".TXT") }, true},
- { { FPL("foo.tXt"), FPL(".txt") }, true},
- { { FPL("foo.txt"), FPL(".tXt") }, true},
- { { FPL("foo.tXt"), FPL(".TXT") }, true},
- { { FPL("foo.tXt"), FPL(".tXt") }, true},
-#if defined(FILE_PATH_USES_DRIVE_LETTERS)
- { { FPL("c:/foo.txt.dll"), FPL(".txt") }, false},
- { { FPL("c:/foo.txt"), FPL(".txt") }, true},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- { { FPL("c:\\bar\\foo.txt.dll"), FPL(".txt") }, false},
- { { FPL("c:\\bar\\foo.txt"), FPL(".txt") }, true},
-#endif // FILE_PATH_USES_DRIVE_LETTERS
- { { FPL("/bar/foo.txt.dll"), FPL(".txt") }, false},
- { { FPL("/bar/foo.txt"), FPL(".txt") }, true},
-#if defined(OS_WIN) || defined(OS_MACOSX)
- // Umlauts A, O, U: direct comparison, and upper case vs. lower case
- { { FPL("foo.\u00E4\u00F6\u00FC"), FPL(".\u00E4\u00F6\u00FC") }, true},
- { { FPL("foo.\u00C4\u00D6\u00DC"), FPL(".\u00E4\u00F6\u00FC") }, true},
- // C with circumflex: direct comparison, and upper case vs. lower case
- { { FPL("foo.\u0109"), FPL(".\u0109") }, true},
- { { FPL("foo.\u0108"), FPL(".\u0109") }, true},
-#endif
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath path(cases[i].inputs[0]);
- FilePath::StringType ext(cases[i].inputs[1]);
-
- EXPECT_EQ(cases[i].expected, path.MatchesExtension(ext)) <<
- "i: " << i << ", path: " << path.value() << ", ext: " << ext;
- }
-}
-
-TEST_F(FilePathTest, CompareIgnoreCase) {
- const struct BinaryIntTestData cases[] = {
- { { FPL("foo"), FPL("foo") }, 0},
- { { FPL("FOO"), FPL("foo") }, 0},
- { { FPL("foo.ext"), FPL("foo.ext") }, 0},
- { { FPL("FOO.EXT"), FPL("foo.ext") }, 0},
- { { FPL("Foo.Ext"), FPL("foo.ext") }, 0},
- { { FPL("foO"), FPL("foo") }, 0},
- { { FPL("foo"), FPL("foO") }, 0},
- { { FPL("fOo"), FPL("foo") }, 0},
- { { FPL("foo"), FPL("fOo") }, 0},
- { { FPL("bar"), FPL("foo") }, -1},
- { { FPL("foo"), FPL("bar") }, 1},
- { { FPL("BAR"), FPL("foo") }, -1},
- { { FPL("FOO"), FPL("bar") }, 1},
- { { FPL("bar"), FPL("FOO") }, -1},
- { { FPL("foo"), FPL("BAR") }, 1},
- { { FPL("BAR"), FPL("FOO") }, -1},
- { { FPL("FOO"), FPL("BAR") }, 1},
- // German "Eszett" (lower case and the new-fangled upper case)
- // Note that uc(<lowercase eszett>) => "SS", NOT <uppercase eszett>!
- // However, neither Windows nor Mac OSX converts these.
- // (or even have glyphs for <uppercase eszett>)
- { { FPL("\u00DF"), FPL("\u00DF") }, 0},
- { { FPL("\u1E9E"), FPL("\u1E9E") }, 0},
- { { FPL("\u00DF"), FPL("\u1E9E") }, -1},
- { { FPL("SS"), FPL("\u00DF") }, -1},
- { { FPL("SS"), FPL("\u1E9E") }, -1},
-#if defined(OS_WIN) || defined(OS_MACOSX)
- // Umlauts A, O, U: direct comparison, and upper case vs. lower case
- { { FPL("\u00E4\u00F6\u00FC"), FPL("\u00E4\u00F6\u00FC") }, 0},
- { { FPL("\u00C4\u00D6\u00DC"), FPL("\u00E4\u00F6\u00FC") }, 0},
- // C with circumflex: direct comparison, and upper case vs. lower case
- { { FPL("\u0109"), FPL("\u0109") }, 0},
- { { FPL("\u0108"), FPL("\u0109") }, 0},
- // Cyrillic letter SHA: direct comparison, and upper case vs. lower case
- { { FPL("\u0428"), FPL("\u0428") }, 0},
- { { FPL("\u0428"), FPL("\u0448") }, 0},
- // Greek letter DELTA: direct comparison, and upper case vs. lower case
- { { FPL("\u0394"), FPL("\u0394") }, 0},
- { { FPL("\u0394"), FPL("\u03B4") }, 0},
- // Japanese full-width A: direct comparison, and upper case vs. lower case
- // Note that full-width and standard characters are considered different.
- { { FPL("\uFF21"), FPL("\uFF21") }, 0},
- { { FPL("\uFF21"), FPL("\uFF41") }, 0},
- { { FPL("A"), FPL("\uFF21") }, -1},
- { { FPL("A"), FPL("\uFF41") }, -1},
- { { FPL("a"), FPL("\uFF21") }, -1},
- { { FPL("a"), FPL("\uFF41") }, -1},
-#endif
-#if defined(OS_MACOSX)
- // Codepoints > 0x1000
- // Georgian letter DON: direct comparison, and upper case vs. lower case
- { { FPL("\u10A3"), FPL("\u10A3") }, 0},
- { { FPL("\u10A3"), FPL("\u10D3") }, 0},
- // Combining characters vs. pre-composed characters, upper and lower case
- { { FPL("k\u0301u\u032Do\u0304\u0301n"), FPL("\u1E31\u1E77\u1E53n") }, 0},
- { { FPL("k\u0301u\u032Do\u0304\u0301n"), FPL("kuon") }, 1},
- { { FPL("kuon"), FPL("k\u0301u\u032Do\u0304\u0301n") }, -1},
- { { FPL("K\u0301U\u032DO\u0304\u0301N"), FPL("KUON") }, 1},
- { { FPL("KUON"), FPL("K\u0301U\u032DO\u0304\u0301N") }, -1},
- { { FPL("k\u0301u\u032Do\u0304\u0301n"), FPL("KUON") }, 1},
- { { FPL("K\u0301U\u032DO\u0304\u0301N"), FPL("\u1E31\u1E77\u1E53n") }, 0},
- { { FPL("k\u0301u\u032Do\u0304\u0301n"), FPL("\u1E30\u1E76\u1E52n") }, 0},
- { { FPL("k\u0301u\u032Do\u0304\u0302n"), FPL("\u1E30\u1E76\u1E52n") }, 1},
-#endif
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath::StringType s1(cases[i].inputs[0]);
- FilePath::StringType s2(cases[i].inputs[1]);
- int result = FilePath::CompareIgnoreCase(s1, s2);
- EXPECT_EQ(cases[i].expected, result) <<
- "i: " << i << ", s1: " << s1 << ", s2: " << s2;
- }
-}
-
-TEST_F(FilePathTest, ReferencesParent) {
- const struct UnaryBooleanTestData cases[] = {
- { FPL("."), false },
- { FPL(".."), true },
- { FPL(".. "), true },
- { FPL(" .."), true },
- { FPL("..."), true },
- { FPL("a.."), false },
- { FPL("..a"), false },
- { FPL("../"), true },
- { FPL("/.."), true },
- { FPL("/../"), true },
- { FPL("/a../"), false },
- { FPL("/..a/"), false },
- { FPL("//.."), true },
- { FPL("..//"), true },
- { FPL("//..//"), true },
- { FPL("a//..//c"), true },
- { FPL("../b/c"), true },
- { FPL("/../b/c"), true },
- { FPL("a/b/.."), true },
- { FPL("a/b/../"), true },
- { FPL("a/../c"), true },
- { FPL("a/b/c"), false },
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- bool observed = input.ReferencesParent();
- EXPECT_EQ(cases[i].expected, observed) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-
-TEST_F(FilePathTest, FromUTF8Unsafe_And_AsUTF8Unsafe) {
- const struct UTF8TestData cases[] = {
- { FPL("foo.txt"), "foo.txt" },
- // "aeo" with accents. Use http://0xcc.net/jsescape/ to decode them.
- { FPL("\u00E0\u00E8\u00F2.txt"), "\xC3\xA0\xC3\xA8\xC3\xB2.txt" },
- // Full-width "ABC".
- { FPL("\uFF21\uFF22\uFF23.txt"),
- "\xEF\xBC\xA1\xEF\xBC\xA2\xEF\xBC\xA3.txt" },
- };
-
-#if !defined(SYSTEM_NATIVE_UTF8) && defined(OS_LINUX)
- ScopedLocale locale("en_US.UTF-8");
-#endif
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- // Test FromUTF8Unsafe() works.
- FilePath from_utf8 = FilePath::FromUTF8Unsafe(cases[i].utf8);
- EXPECT_EQ(cases[i].native, from_utf8.value())
- << "i: " << i << ", input: " << cases[i].native;
- // Test AsUTF8Unsafe() works.
- FilePath from_native = FilePath(cases[i].native);
- EXPECT_EQ(cases[i].utf8, from_native.AsUTF8Unsafe())
- << "i: " << i << ", input: " << cases[i].native;
- // Test the two file paths are identical.
- EXPECT_EQ(from_utf8.value(), from_native.value());
- }
-}
-
-TEST_F(FilePathTest, ConstructWithNUL) {
- // Assert FPS() works.
- ASSERT_EQ(3U, FPS("a\0b").length());
-
- // Test constructor strips '\0'
- FilePath path(FPS("a\0b"));
- EXPECT_EQ(1U, path.value().length());
- EXPECT_EQ(FPL("a"), path.value());
-}
-
-TEST_F(FilePathTest, AppendWithNUL) {
- // Assert FPS() works.
- ASSERT_EQ(3U, FPS("b\0b").length());
-
- // Test Append() strips '\0'
- FilePath path(FPL("a"));
- path = path.Append(FPS("b\0b"));
- EXPECT_EQ(3U, path.value().length());
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
- EXPECT_EQ(FPL("a\\b"), path.value());
-#else
- EXPECT_EQ(FPL("a/b"), path.value());
-#endif
-}
-
-TEST_F(FilePathTest, ReferencesParentWithNUL) {
- // Assert FPS() works.
- ASSERT_EQ(3U, FPS("..\0").length());
-
- // Test ReferencesParent() doesn't break with "..\0"
- FilePath path(FPS("..\0"));
- EXPECT_TRUE(path.ReferencesParent());
-}
-
-#if defined(FILE_PATH_USES_WIN_SEPARATORS)
-TEST_F(FilePathTest, NormalizePathSeparators) {
- const struct UnaryTestData cases[] = {
- { FPL("foo/bar"), FPL("foo\\bar") },
- { FPL("foo/bar\\betz"), FPL("foo\\bar\\betz") },
- { FPL("foo\\bar"), FPL("foo\\bar") },
- { FPL("foo\\bar/betz"), FPL("foo\\bar\\betz") },
- { FPL("foo"), FPL("foo") },
- // Trailing slashes don't automatically get stripped. That's what
- // StripTrailingSeparators() is for.
- { FPL("foo\\"), FPL("foo\\") },
- { FPL("foo/"), FPL("foo\\") },
- { FPL("foo/bar\\"), FPL("foo\\bar\\") },
- { FPL("foo\\bar/"), FPL("foo\\bar\\") },
- { FPL("foo/bar/"), FPL("foo\\bar\\") },
- { FPL("foo\\bar\\"), FPL("foo\\bar\\") },
- { FPL("\\foo/bar"), FPL("\\foo\\bar") },
- { FPL("/foo\\bar"), FPL("\\foo\\bar") },
- { FPL("c:/foo/bar/"), FPL("c:\\foo\\bar\\") },
- { FPL("/foo/bar/"), FPL("\\foo\\bar\\") },
- { FPL("\\foo\\bar\\"), FPL("\\foo\\bar\\") },
- { FPL("c:\\foo/bar"), FPL("c:\\foo\\bar") },
- { FPL("//foo\\bar\\"), FPL("\\\\foo\\bar\\") },
- { FPL("\\\\foo\\bar\\"), FPL("\\\\foo\\bar\\") },
- { FPL("//foo\\bar\\"), FPL("\\\\foo\\bar\\") },
- // This method does not normalize the number of path separators.
- { FPL("foo\\\\bar"), FPL("foo\\\\bar") },
- { FPL("foo//bar"), FPL("foo\\\\bar") },
- { FPL("foo/\\bar"), FPL("foo\\\\bar") },
- { FPL("foo\\/bar"), FPL("foo\\\\bar") },
- { FPL("///foo\\\\bar"), FPL("\\\\\\foo\\\\bar") },
- { FPL("foo//bar///"), FPL("foo\\\\bar\\\\\\") },
- { FPL("foo/\\bar/\\"), FPL("foo\\\\bar\\\\") },
- { FPL("/\\foo\\/bar"), FPL("\\\\foo\\\\bar") },
- };
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- FilePath observed = input.NormalizePathSeparators();
- EXPECT_EQ(FilePath::StringType(cases[i].expected), observed.value()) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-#endif
-
-TEST_F(FilePathTest, EndsWithSeparator) {
- const UnaryBooleanTestData cases[] = {
- { FPL(""), false },
- { FPL("/"), true },
- { FPL("foo/"), true },
- { FPL("bar"), false },
- { FPL("/foo/bar"), false },
- };
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input = FilePath(cases[i].input).NormalizePathSeparators();
- EXPECT_EQ(cases[i].expected, input.EndsWithSeparator());
- }
-}
-
-TEST_F(FilePathTest, AsEndingWithSeparator) {
- const UnaryTestData cases[] = {
- { FPL(""), FPL("") },
- { FPL("/"), FPL("/") },
- { FPL("foo"), FPL("foo/") },
- { FPL("foo/"), FPL("foo/") }
- };
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input = FilePath(cases[i].input).NormalizePathSeparators();
- FilePath expected = FilePath(cases[i].expected).NormalizePathSeparators();
- EXPECT_EQ(expected.value(), input.AsEndingWithSeparator().value());
- }
-}
-
-#if defined(OS_ANDROID)
-TEST_F(FilePathTest, ContentUriTest) {
- const struct UnaryBooleanTestData cases[] = {
- { FPL("content://foo.bar"), true },
- { FPL("content://foo.bar/"), true },
- { FPL("content://foo/bar"), true },
- { FPL("CoNTenT://foo.bar"), true },
- { FPL("content://"), true },
- { FPL("content:///foo.bar"), true },
- { FPL("content://3foo/bar"), true },
- { FPL("content://_foo/bar"), true },
- { FPL(".. "), false },
- { FPL("foo.bar"), false },
- { FPL("content:foo.bar"), false },
- { FPL("content:/foo.ba"), false },
- { FPL("content:/dir/foo.bar"), false },
- { FPL("content: //foo.bar"), false },
- { FPL("content%2a%2f%2f"), false },
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- FilePath input(cases[i].input);
- bool observed = input.IsContentUri();
- EXPECT_EQ(cases[i].expected, observed) <<
- "i: " << i << ", input: " << input.value();
- }
-}
-#endif
-
-// Test the operator<<(ostream, FilePath).
-TEST_F(FilePathTest, PrintToOstream) {
- std::stringstream ss;
- FilePath fp(FPL("foo"));
- ss << fp;
- EXPECT_EQ("foo", ss.str());
-}
-
-// Test GetHFSDecomposedForm should return empty result for invalid UTF-8
-// strings.
-#if defined(OS_MACOSX)
-TEST_F(FilePathTest, GetHFSDecomposedFormWithInvalidInput) {
- const FilePath::CharType* cases[] = {
- FPL("\xc3\x28"),
- FPL("\xe2\x82\x28"),
- FPL("\xe2\x28\xa1"),
- FPL("\xf0\x28\x8c\xbc"),
- FPL("\xf0\x28\x8c\x28"),
- };
- for (auto* invalid_input : cases) {
- FilePath::StringType observed = FilePath::GetHFSDecomposedForm(
- invalid_input);
- EXPECT_TRUE(observed.empty());
- }
-}
-#endif
-
-} // namespace base
diff --git a/base/files/file_path_watcher_unittest.cc b/base/files/file_path_watcher_unittest.cc
deleted file mode 100644
index 9e3d94d..0000000
--- a/base/files/file_path_watcher_unittest.cc
+++ /dev/null
@@ -1,873 +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.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include <aclapi.h>
-#elif defined(OS_POSIX)
-#include <sys/stat.h>
-#endif
-
-#include <set>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.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/stl_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/test_file_util.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/path_utils.h"
-#endif // defined(OS_ANDROID)
-
-#if defined(OS_POSIX)
-#include "base/files/file_descriptor_watcher_posix.h"
-#endif // defined(OS_POSIX)
-
-namespace base {
-
-namespace {
-
-class TestDelegate;
-
-// Aggregates notifications from the test delegates and breaks the message loop
-// the test thread is waiting on once they all came in.
-class NotificationCollector
- : public base::RefCountedThreadSafe<NotificationCollector> {
- public:
- NotificationCollector() : task_runner_(base::ThreadTaskRunnerHandle::Get()) {}
-
- // Called from the file thread by the delegates.
- void OnChange(TestDelegate* delegate) {
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(&NotificationCollector::RecordChange, this,
- base::Unretained(delegate)));
- }
-
- void Register(TestDelegate* delegate) {
- delegates_.insert(delegate);
- }
-
- void Reset() {
- signaled_.clear();
- }
-
- bool Success() {
- return signaled_ == delegates_;
- }
-
- private:
- friend class base::RefCountedThreadSafe<NotificationCollector>;
- ~NotificationCollector() = default;
-
- void RecordChange(TestDelegate* delegate) {
- // Warning: |delegate| is Unretained. Do not dereference.
- ASSERT_TRUE(task_runner_->BelongsToCurrentThread());
- ASSERT_TRUE(delegates_.count(delegate));
- signaled_.insert(delegate);
-
- // Check whether all delegates have been signaled.
- if (signaled_ == delegates_)
- task_runner_->PostTask(FROM_HERE,
- RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- }
-
- // Set of registered delegates.
- std::set<TestDelegate*> delegates_;
-
- // Set of signaled delegates.
- std::set<TestDelegate*> signaled_;
-
- // The loop we should break after all delegates signaled.
- scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
-};
-
-class TestDelegateBase : public SupportsWeakPtr<TestDelegateBase> {
- public:
- TestDelegateBase() = default;
- virtual ~TestDelegateBase() = default;
-
- virtual void OnFileChanged(const FilePath& path, bool error) = 0;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestDelegateBase);
-};
-
-// A mock class for testing. Gmock is not appropriate because it is not
-// thread-safe for setting expectations. Thus the test code cannot safely
-// reset expectations while the file watcher is running.
-// Instead, TestDelegate gets the notifications from FilePathWatcher and uses
-// NotificationCollector to aggregate the results.
-class TestDelegate : public TestDelegateBase {
- public:
- explicit TestDelegate(NotificationCollector* collector)
- : collector_(collector) {
- collector_->Register(this);
- }
- ~TestDelegate() override = default;
-
- void OnFileChanged(const FilePath& path, bool error) override {
- if (error)
- ADD_FAILURE() << "Error " << path.value();
- else
- collector_->OnChange(this);
- }
-
- private:
- scoped_refptr<NotificationCollector> collector_;
-
- DISALLOW_COPY_AND_ASSIGN(TestDelegate);
-};
-
-class FilePathWatcherTest : public testing::Test {
- public:
- FilePathWatcherTest()
-#if defined(OS_POSIX)
- : file_descriptor_watcher_(&loop_)
-#endif
- {
- }
-
- ~FilePathWatcherTest() override = default;
-
- protected:
- void SetUp() override {
-#if defined(OS_ANDROID)
- // Watching files is only permitted when all parent directories are
- // accessible, which is not the case for the default temp directory
- // on Android which is under /data/data. Use /sdcard instead.
- // TODO(pauljensen): Remove this when crbug.com/475568 is fixed.
- FilePath parent_dir;
- ASSERT_TRUE(android::GetExternalStorageDirectory(&parent_dir));
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDirUnderPath(parent_dir));
-#else // defined(OS_ANDROID)
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
-#endif // defined(OS_ANDROID)
- collector_ = new NotificationCollector();
- }
-
- void TearDown() override { RunLoop().RunUntilIdle(); }
-
- FilePath test_file() {
- return temp_dir_.GetPath().AppendASCII("FilePathWatcherTest");
- }
-
- FilePath test_link() {
- return temp_dir_.GetPath().AppendASCII("FilePathWatcherTest.lnk");
- }
-
- // Write |content| to |file|. Returns true on success.
- bool WriteFile(const FilePath& file, const std::string& content) {
- int write_size = ::base::WriteFile(file, content.c_str(), content.length());
- return write_size == static_cast<int>(content.length());
- }
-
- bool SetupWatch(const FilePath& target,
- FilePathWatcher* watcher,
- TestDelegateBase* delegate,
- bool recursive_watch) WARN_UNUSED_RESULT;
-
- bool WaitForEvents() WARN_UNUSED_RESULT {
- collector_->Reset();
-
- RunLoop run_loop;
- // Make sure we timeout if we don't get notified.
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitWhenIdleClosure(),
- TestTimeouts::action_timeout());
- run_loop.Run();
- return collector_->Success();
- }
-
- NotificationCollector* collector() { return collector_.get(); }
-
- MessageLoopForIO loop_;
-#if defined(OS_POSIX)
- FileDescriptorWatcher file_descriptor_watcher_;
-#endif
-
- ScopedTempDir temp_dir_;
- scoped_refptr<NotificationCollector> collector_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(FilePathWatcherTest);
-};
-
-bool FilePathWatcherTest::SetupWatch(const FilePath& target,
- FilePathWatcher* watcher,
- TestDelegateBase* delegate,
- bool recursive_watch) {
- return watcher->Watch(
- target, recursive_watch,
- base::Bind(&TestDelegateBase::OnFileChanged, delegate->AsWeakPtr()));
-}
-
-// Basic test: Create the file and verify that we notice.
-TEST_F(FilePathWatcherTest, NewFile) {
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
-
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that modifying the file is caught.
-TEST_F(FilePathWatcherTest, ModifiedFile) {
- ASSERT_TRUE(WriteFile(test_file(), "content"));
-
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the file is modified.
- ASSERT_TRUE(WriteFile(test_file(), "new content"));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that moving the file into place is caught.
-TEST_F(FilePathWatcherTest, MovedFile) {
- FilePath source_file(temp_dir_.GetPath().AppendASCII("source"));
- ASSERT_TRUE(WriteFile(source_file, "content"));
-
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the file is modified.
- ASSERT_TRUE(base::Move(source_file, test_file()));
- ASSERT_TRUE(WaitForEvents());
-}
-
-TEST_F(FilePathWatcherTest, DeletedFile) {
- ASSERT_TRUE(WriteFile(test_file(), "content"));
-
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the file is deleted.
- base::DeleteFile(test_file(), false);
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Used by the DeleteDuringNotify test below.
-// Deletes the FilePathWatcher when it's notified.
-class Deleter : public TestDelegateBase {
- public:
- Deleter(FilePathWatcher* watcher, MessageLoop* loop)
- : watcher_(watcher),
- loop_(loop) {
- }
- ~Deleter() override = default;
-
- void OnFileChanged(const FilePath&, bool) override {
- watcher_.reset();
- loop_->task_runner()->PostTask(
- FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- }
-
- FilePathWatcher* watcher() const { return watcher_.get(); }
-
- private:
- std::unique_ptr<FilePathWatcher> watcher_;
- MessageLoop* loop_;
-
- DISALLOW_COPY_AND_ASSIGN(Deleter);
-};
-
-// Verify that deleting a watcher during the callback doesn't crash.
-TEST_F(FilePathWatcherTest, DeleteDuringNotify) {
- FilePathWatcher* watcher = new FilePathWatcher;
- // Takes ownership of watcher.
- std::unique_ptr<Deleter> deleter(new Deleter(watcher, &loop_));
- ASSERT_TRUE(SetupWatch(test_file(), watcher, deleter.get(), false));
-
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(WaitForEvents());
-
- // We win if we haven't crashed yet.
- // Might as well double-check it got deleted, too.
- ASSERT_TRUE(deleter->watcher() == nullptr);
-}
-
-// Verify that deleting the watcher works even if there is a pending
-// notification.
-// Flaky on MacOS (and ARM linux): http://crbug.com/85930
-TEST_F(FilePathWatcherTest, DISABLED_DestroyWithPendingNotification) {
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- FilePathWatcher watcher;
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
- ASSERT_TRUE(WriteFile(test_file(), "content"));
-}
-
-TEST_F(FilePathWatcherTest, MultipleWatchersSingleFile) {
- FilePathWatcher watcher1, watcher2;
- std::unique_ptr<TestDelegate> delegate1(new TestDelegate(collector()));
- std::unique_ptr<TestDelegate> delegate2(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher1, delegate1.get(), false));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher2, delegate2.get(), false));
-
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that watching a file whose parent directory doesn't exist yet works if
-// the directory and file are created eventually.
-TEST_F(FilePathWatcherTest, NonExistentDirectory) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath file(dir.AppendASCII("file"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(file, &watcher, delegate.get(), false));
-
- ASSERT_TRUE(base::CreateDirectory(dir));
-
- ASSERT_TRUE(WriteFile(file, "content"));
-
- VLOG(1) << "Waiting for file creation";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file, "content v2"));
- VLOG(1) << "Waiting for file change";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(base::DeleteFile(file, false));
- VLOG(1) << "Waiting for file deletion";
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Exercises watch reconfiguration for the case that directories on the path
-// are rapidly created.
-TEST_F(FilePathWatcherTest, DirectoryChain) {
- FilePath path(temp_dir_.GetPath());
- std::vector<std::string> dir_names;
- for (int i = 0; i < 20; i++) {
- std::string dir(base::StringPrintf("d%d", i));
- dir_names.push_back(dir);
- path = path.AppendASCII(dir);
- }
-
- FilePathWatcher watcher;
- FilePath file(path.AppendASCII("file"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(file, &watcher, delegate.get(), false));
-
- FilePath sub_path(temp_dir_.GetPath());
- for (std::vector<std::string>::const_iterator d(dir_names.begin());
- d != dir_names.end(); ++d) {
- sub_path = sub_path.AppendASCII(*d);
- ASSERT_TRUE(base::CreateDirectory(sub_path));
- }
- VLOG(1) << "Create File";
- ASSERT_TRUE(WriteFile(file, "content"));
- VLOG(1) << "Waiting for file creation";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file, "content v2"));
- VLOG(1) << "Waiting for file modification";
- ASSERT_TRUE(WaitForEvents());
-}
-
-#if defined(OS_MACOSX)
-// http://crbug.com/85930
-#define DisappearingDirectory DISABLED_DisappearingDirectory
-#endif
-TEST_F(FilePathWatcherTest, DisappearingDirectory) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath file(dir.AppendASCII("file"));
- ASSERT_TRUE(base::CreateDirectory(dir));
- ASSERT_TRUE(WriteFile(file, "content"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(file, &watcher, delegate.get(), false));
-
- ASSERT_TRUE(base::DeleteFile(dir, true));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Tests that a file that is deleted and reappears is tracked correctly.
-TEST_F(FilePathWatcherTest, DeleteAndRecreate) {
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
-
- ASSERT_TRUE(base::DeleteFile(test_file(), false));
- VLOG(1) << "Waiting for file deletion";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- VLOG(1) << "Waiting for file creation";
- ASSERT_TRUE(WaitForEvents());
-}
-
-TEST_F(FilePathWatcherTest, WatchDirectory) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath file1(dir.AppendASCII("file1"));
- FilePath file2(dir.AppendASCII("file2"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(dir, &watcher, delegate.get(), false));
-
- ASSERT_TRUE(base::CreateDirectory(dir));
- VLOG(1) << "Waiting for directory creation";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file1, "content"));
- VLOG(1) << "Waiting for file1 creation";
- ASSERT_TRUE(WaitForEvents());
-
-#if !defined(OS_MACOSX)
- // Mac implementation does not detect files modified in a directory.
- ASSERT_TRUE(WriteFile(file1, "content v2"));
- VLOG(1) << "Waiting for file1 modification";
- ASSERT_TRUE(WaitForEvents());
-#endif // !OS_MACOSX
-
- ASSERT_TRUE(base::DeleteFile(file1, false));
- VLOG(1) << "Waiting for file1 deletion";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file2, "content"));
- VLOG(1) << "Waiting for file2 creation";
- ASSERT_TRUE(WaitForEvents());
-}
-
-TEST_F(FilePathWatcherTest, MoveParent) {
- FilePathWatcher file_watcher;
- FilePathWatcher subdir_watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath dest(temp_dir_.GetPath().AppendASCII("dest"));
- FilePath subdir(dir.AppendASCII("subdir"));
- FilePath file(subdir.AppendASCII("file"));
- std::unique_ptr<TestDelegate> file_delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(file, &file_watcher, file_delegate.get(), false));
- std::unique_ptr<TestDelegate> subdir_delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(subdir, &subdir_watcher, subdir_delegate.get(),
- false));
-
- // Setup a directory hierarchy.
- ASSERT_TRUE(base::CreateDirectory(subdir));
- ASSERT_TRUE(WriteFile(file, "content"));
- VLOG(1) << "Waiting for file creation";
- ASSERT_TRUE(WaitForEvents());
-
- // Move the parent directory.
- base::Move(dir, dest);
- VLOG(1) << "Waiting for directory move";
- ASSERT_TRUE(WaitForEvents());
-}
-
-TEST_F(FilePathWatcherTest, RecursiveWatch) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- bool setup_result = SetupWatch(dir, &watcher, delegate.get(), true);
- if (!FilePathWatcher::RecursiveWatchAvailable()) {
- ASSERT_FALSE(setup_result);
- return;
- }
- ASSERT_TRUE(setup_result);
-
- // Main directory("dir") creation.
- ASSERT_TRUE(base::CreateDirectory(dir));
- ASSERT_TRUE(WaitForEvents());
-
- // Create "$dir/file1".
- FilePath file1(dir.AppendASCII("file1"));
- ASSERT_TRUE(WriteFile(file1, "content"));
- ASSERT_TRUE(WaitForEvents());
-
- // Create "$dir/subdir".
- FilePath subdir(dir.AppendASCII("subdir"));
- ASSERT_TRUE(base::CreateDirectory(subdir));
- ASSERT_TRUE(WaitForEvents());
-
- // Create "$dir/subdir/subdir_file1".
- FilePath subdir_file1(subdir.AppendASCII("subdir_file1"));
- ASSERT_TRUE(WriteFile(subdir_file1, "content"));
- ASSERT_TRUE(WaitForEvents());
-
- // Create "$dir/subdir/subdir_child_dir".
- FilePath subdir_child_dir(subdir.AppendASCII("subdir_child_dir"));
- ASSERT_TRUE(base::CreateDirectory(subdir_child_dir));
- ASSERT_TRUE(WaitForEvents());
-
- // Create "$dir/subdir/subdir_child_dir/child_dir_file1".
- FilePath child_dir_file1(subdir_child_dir.AppendASCII("child_dir_file1"));
- ASSERT_TRUE(WriteFile(child_dir_file1, "content v2"));
- ASSERT_TRUE(WaitForEvents());
-
- // Write into "$dir/subdir/subdir_child_dir/child_dir_file1".
- ASSERT_TRUE(WriteFile(child_dir_file1, "content"));
- ASSERT_TRUE(WaitForEvents());
-
-// Apps cannot change file attributes on Android in /sdcard as /sdcard uses the
-// "fuse" file system, while /data uses "ext4". Running these tests in /data
-// would be preferable and allow testing file attributes and symlinks.
-// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
-// the |temp_dir_| in /data.
-#if !defined(OS_ANDROID)
- // Modify "$dir/subdir/subdir_child_dir/child_dir_file1" attributes.
- ASSERT_TRUE(base::MakeFileUnreadable(child_dir_file1));
- ASSERT_TRUE(WaitForEvents());
-#endif
-
- // Delete "$dir/subdir/subdir_file1".
- ASSERT_TRUE(base::DeleteFile(subdir_file1, false));
- ASSERT_TRUE(WaitForEvents());
-
- // Delete "$dir/subdir/subdir_child_dir/child_dir_file1".
- ASSERT_TRUE(base::DeleteFile(child_dir_file1, false));
- ASSERT_TRUE(WaitForEvents());
-}
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-// Apps cannot create symlinks on Android in /sdcard as /sdcard uses the
-// "fuse" file system, while /data uses "ext4". Running these tests in /data
-// would be preferable and allow testing file attributes and symlinks.
-// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
-// the |temp_dir_| in /data.
-//
-// This test is disabled on Fuchsia since it doesn't support symlinking.
-TEST_F(FilePathWatcherTest, RecursiveWithSymLink) {
- if (!FilePathWatcher::RecursiveWatchAvailable())
- return;
-
- FilePathWatcher watcher;
- FilePath test_dir(temp_dir_.GetPath().AppendASCII("test_dir"));
- ASSERT_TRUE(base::CreateDirectory(test_dir));
- FilePath symlink(test_dir.AppendASCII("symlink"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(symlink, &watcher, delegate.get(), true));
-
- // Link creation.
- FilePath target1(temp_dir_.GetPath().AppendASCII("target1"));
- ASSERT_TRUE(base::CreateSymbolicLink(target1, symlink));
- ASSERT_TRUE(WaitForEvents());
-
- // Target1 creation.
- ASSERT_TRUE(base::CreateDirectory(target1));
- ASSERT_TRUE(WaitForEvents());
-
- // Create a file in target1.
- FilePath target1_file(target1.AppendASCII("file"));
- ASSERT_TRUE(WriteFile(target1_file, "content"));
- ASSERT_TRUE(WaitForEvents());
-
- // Link change.
- FilePath target2(temp_dir_.GetPath().AppendASCII("target2"));
- ASSERT_TRUE(base::CreateDirectory(target2));
- ASSERT_TRUE(base::DeleteFile(symlink, false));
- ASSERT_TRUE(base::CreateSymbolicLink(target2, symlink));
- ASSERT_TRUE(WaitForEvents());
-
- // Create a file in target2.
- FilePath target2_file(target2.AppendASCII("file"));
- ASSERT_TRUE(WriteFile(target2_file, "content"));
- ASSERT_TRUE(WaitForEvents());
-}
-#endif // defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-
-TEST_F(FilePathWatcherTest, MoveChild) {
- FilePathWatcher file_watcher;
- FilePathWatcher subdir_watcher;
- FilePath source_dir(temp_dir_.GetPath().AppendASCII("source"));
- FilePath source_subdir(source_dir.AppendASCII("subdir"));
- FilePath source_file(source_subdir.AppendASCII("file"));
- FilePath dest_dir(temp_dir_.GetPath().AppendASCII("dest"));
- FilePath dest_subdir(dest_dir.AppendASCII("subdir"));
- FilePath dest_file(dest_subdir.AppendASCII("file"));
-
- // Setup a directory hierarchy.
- ASSERT_TRUE(base::CreateDirectory(source_subdir));
- ASSERT_TRUE(WriteFile(source_file, "content"));
-
- std::unique_ptr<TestDelegate> file_delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(dest_file, &file_watcher, file_delegate.get(), false));
- std::unique_ptr<TestDelegate> subdir_delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(dest_subdir, &subdir_watcher, subdir_delegate.get(),
- false));
-
- // Move the directory into place, s.t. the watched file appears.
- ASSERT_TRUE(base::Move(source_dir, dest_dir));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that changing attributes on a file is caught
-#if defined(OS_ANDROID)
-// Apps cannot change file attributes on Android in /sdcard as /sdcard uses the
-// "fuse" file system, while /data uses "ext4". Running these tests in /data
-// would be preferable and allow testing file attributes and symlinks.
-// TODO(pauljensen): Re-enable when crbug.com/475568 is fixed and SetUp() places
-// the |temp_dir_| in /data.
-#define FileAttributesChanged DISABLED_FileAttributesChanged
-#endif // defined(OS_ANDROID
-TEST_F(FilePathWatcherTest, FileAttributesChanged) {
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the file is modified.
- ASSERT_TRUE(base::MakeFileUnreadable(test_file()));
- ASSERT_TRUE(WaitForEvents());
-}
-
-#if defined(OS_LINUX)
-
-// Verify that creating a symlink is caught.
-TEST_F(FilePathWatcherTest, CreateLink) {
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- // Note that we are watching the symlink
- ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the link is created.
- // Note that test_file() doesn't have to exist.
- ASSERT_TRUE(CreateSymbolicLink(test_file(), test_link()));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that deleting a symlink is caught.
-TEST_F(FilePathWatcherTest, DeleteLink) {
- // Unfortunately this test case only works if the link target exists.
- // TODO(craig) fix this as part of crbug.com/91561.
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(CreateSymbolicLink(test_file(), test_link()));
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the link is deleted.
- ASSERT_TRUE(base::DeleteFile(test_link(), false));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that modifying a target file that a link is pointing to
-// when we are watching the link is caught.
-TEST_F(FilePathWatcherTest, ModifiedLinkedFile) {
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(CreateSymbolicLink(test_file(), test_link()));
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- // Note that we are watching the symlink.
- ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the file is modified.
- ASSERT_TRUE(WriteFile(test_file(), "new content"));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that creating a target file that a link is pointing to
-// when we are watching the link is caught.
-TEST_F(FilePathWatcherTest, CreateTargetLinkedFile) {
- ASSERT_TRUE(CreateSymbolicLink(test_file(), test_link()));
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- // Note that we are watching the symlink.
- ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the target file is created.
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that deleting a target file that a link is pointing to
-// when we are watching the link is caught.
-TEST_F(FilePathWatcherTest, DeleteTargetLinkedFile) {
- ASSERT_TRUE(WriteFile(test_file(), "content"));
- ASSERT_TRUE(CreateSymbolicLink(test_file(), test_link()));
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- // Note that we are watching the symlink.
- ASSERT_TRUE(SetupWatch(test_link(), &watcher, delegate.get(), false));
-
- // Now make sure we get notified if the target file is deleted.
- ASSERT_TRUE(base::DeleteFile(test_file(), false));
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that watching a file whose parent directory is a link that
-// doesn't exist yet works if the symlink is created eventually.
-TEST_F(FilePathWatcherTest, LinkedDirectoryPart1) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath link_dir(temp_dir_.GetPath().AppendASCII("dir.lnk"));
- FilePath file(dir.AppendASCII("file"));
- FilePath linkfile(link_dir.AppendASCII("file"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- // dir/file should exist.
- ASSERT_TRUE(base::CreateDirectory(dir));
- ASSERT_TRUE(WriteFile(file, "content"));
- // Note that we are watching dir.lnk/file which doesn't exist yet.
- ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get(), false));
-
- ASSERT_TRUE(CreateSymbolicLink(dir, link_dir));
- VLOG(1) << "Waiting for link creation";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file, "content v2"));
- VLOG(1) << "Waiting for file change";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(base::DeleteFile(file, false));
- VLOG(1) << "Waiting for file deletion";
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that watching a file whose parent directory is a
-// dangling symlink works if the directory is created eventually.
-TEST_F(FilePathWatcherTest, LinkedDirectoryPart2) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath link_dir(temp_dir_.GetPath().AppendASCII("dir.lnk"));
- FilePath file(dir.AppendASCII("file"));
- FilePath linkfile(link_dir.AppendASCII("file"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- // Now create the link from dir.lnk pointing to dir but
- // neither dir nor dir/file exist yet.
- ASSERT_TRUE(CreateSymbolicLink(dir, link_dir));
- // Note that we are watching dir.lnk/file.
- ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get(), false));
-
- ASSERT_TRUE(base::CreateDirectory(dir));
- ASSERT_TRUE(WriteFile(file, "content"));
- VLOG(1) << "Waiting for dir/file creation";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file, "content v2"));
- VLOG(1) << "Waiting for file change";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(base::DeleteFile(file, false));
- VLOG(1) << "Waiting for file deletion";
- ASSERT_TRUE(WaitForEvents());
-}
-
-// Verify that watching a file with a symlink on the path
-// to the file works.
-TEST_F(FilePathWatcherTest, LinkedDirectoryPart3) {
- FilePathWatcher watcher;
- FilePath dir(temp_dir_.GetPath().AppendASCII("dir"));
- FilePath link_dir(temp_dir_.GetPath().AppendASCII("dir.lnk"));
- FilePath file(dir.AppendASCII("file"));
- FilePath linkfile(link_dir.AppendASCII("file"));
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(base::CreateDirectory(dir));
- ASSERT_TRUE(CreateSymbolicLink(dir, link_dir));
- // Note that we are watching dir.lnk/file but the file doesn't exist yet.
- ASSERT_TRUE(SetupWatch(linkfile, &watcher, delegate.get(), false));
-
- ASSERT_TRUE(WriteFile(file, "content"));
- VLOG(1) << "Waiting for file creation";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(WriteFile(file, "content v2"));
- VLOG(1) << "Waiting for file change";
- ASSERT_TRUE(WaitForEvents());
-
- ASSERT_TRUE(base::DeleteFile(file, false));
- VLOG(1) << "Waiting for file deletion";
- ASSERT_TRUE(WaitForEvents());
-}
-
-#endif // OS_LINUX
-
-enum Permission {
- Read,
- Write,
- Execute
-};
-
-#if defined(OS_MACOSX)
-bool ChangeFilePermissions(const FilePath& path, Permission perm, bool allow) {
- struct stat stat_buf;
-
- if (stat(path.value().c_str(), &stat_buf) != 0)
- return false;
-
- mode_t mode = 0;
- switch (perm) {
- case Read:
- mode = S_IRUSR | S_IRGRP | S_IROTH;
- break;
- case Write:
- mode = S_IWUSR | S_IWGRP | S_IWOTH;
- break;
- case Execute:
- mode = S_IXUSR | S_IXGRP | S_IXOTH;
- break;
- default:
- ADD_FAILURE() << "unknown perm " << perm;
- return false;
- }
- if (allow) {
- stat_buf.st_mode |= mode;
- } else {
- stat_buf.st_mode &= ~mode;
- }
- return chmod(path.value().c_str(), stat_buf.st_mode) == 0;
-}
-#endif // defined(OS_MACOSX)
-
-#if defined(OS_MACOSX)
-// Linux implementation of FilePathWatcher doesn't catch attribute changes.
-// http://crbug.com/78043
-// Windows implementation of FilePathWatcher catches attribute changes that
-// don't affect the path being watched.
-// http://crbug.com/78045
-
-// Verify that changing attributes on a directory works.
-TEST_F(FilePathWatcherTest, DirAttributesChanged) {
- FilePath test_dir1(
- temp_dir_.GetPath().AppendASCII("DirAttributesChangedDir1"));
- FilePath test_dir2(test_dir1.AppendASCII("DirAttributesChangedDir2"));
- FilePath test_file(test_dir2.AppendASCII("DirAttributesChangedFile"));
- // Setup a directory hierarchy.
- ASSERT_TRUE(base::CreateDirectory(test_dir1));
- ASSERT_TRUE(base::CreateDirectory(test_dir2));
- ASSERT_TRUE(WriteFile(test_file, "content"));
-
- FilePathWatcher watcher;
- std::unique_ptr<TestDelegate> delegate(new TestDelegate(collector()));
- ASSERT_TRUE(SetupWatch(test_file, &watcher, delegate.get(), false));
-
- // We should not get notified in this case as it hasn't affected our ability
- // to access the file.
- ASSERT_TRUE(ChangeFilePermissions(test_dir1, Read, false));
- loop_.task_runner()->PostDelayedTask(
- FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated(),
- TestTimeouts::tiny_timeout());
- ASSERT_FALSE(WaitForEvents());
- ASSERT_TRUE(ChangeFilePermissions(test_dir1, Read, true));
-
- // We should get notified in this case because filepathwatcher can no
- // longer access the file
- ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, false));
- ASSERT_TRUE(WaitForEvents());
- ASSERT_TRUE(ChangeFilePermissions(test_dir1, Execute, true));
-}
-
-#endif // OS_MACOSX
-} // namespace
-
-} // namespace base
diff --git a/base/files/file_proxy_unittest.cc b/base/files/file_proxy_unittest.cc
deleted file mode 100644
index 73a0497..0000000
--- a/base/files/file_proxy_unittest.cc
+++ /dev/null
@@ -1,399 +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_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)
-// Flaky on Android, see http://crbug.com/489602
-#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_unittest.cc b/base/files/file_unittest.cc
deleted file mode 100644
index b9992ad..0000000
--- a/base/files/file_unittest.cc
+++ /dev/null
@@ -1,721 +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.h"
-
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/files/file_util.h"
-#include "base/files/memory_mapped_file.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::File;
-using base::FilePath;
-
-TEST(FileTest, Create) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
-
- {
- // Don't create a File at all.
- File file;
- EXPECT_FALSE(file.IsValid());
- EXPECT_EQ(base::File::FILE_ERROR_FAILED, file.error_details());
-
- File file2(base::File::FILE_ERROR_TOO_MANY_OPENED);
- EXPECT_FALSE(file2.IsValid());
- EXPECT_EQ(base::File::FILE_ERROR_TOO_MANY_OPENED, file2.error_details());
- }
-
- {
- // Open a file that doesn't exist.
- File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
- EXPECT_FALSE(file.IsValid());
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, file.error_details());
- EXPECT_EQ(base::File::FILE_ERROR_NOT_FOUND, base::File::GetLastFileError());
- }
-
- {
- // Open or create a file.
- File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ);
- EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file.created());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
- }
-
- {
- // Open an existing file.
- File file(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
- EXPECT_TRUE(file.IsValid());
- EXPECT_FALSE(file.created());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
-
- // This time verify closing the file.
- file.Close();
- EXPECT_FALSE(file.IsValid());
- }
-
- {
- // Open an existing file through Initialize
- File file;
- file.Initialize(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
- EXPECT_TRUE(file.IsValid());
- EXPECT_FALSE(file.created());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
-
- // This time verify closing the file.
- file.Close();
- EXPECT_FALSE(file.IsValid());
- }
-
- {
- // Create a file that exists.
- File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_READ);
- EXPECT_FALSE(file.IsValid());
- EXPECT_FALSE(file.created());
- EXPECT_EQ(base::File::FILE_ERROR_EXISTS, file.error_details());
- EXPECT_EQ(base::File::FILE_ERROR_EXISTS, base::File::GetLastFileError());
- }
-
- {
- // Create or overwrite a file.
- File file(file_path,
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file.created());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
- }
-
- {
- // Create a delete-on-close file.
- file_path = temp_dir.GetPath().AppendASCII("create_file_2");
- File file(file_path,
- base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
- base::File::FLAG_DELETE_ON_CLOSE);
- EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file.created());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
- }
-
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-TEST(FileTest, SelfSwap) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
- File file(file_path,
- base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_DELETE_ON_CLOSE);
- std::swap(file, file);
- EXPECT_TRUE(file.IsValid());
-}
-
-TEST(FileTest, Async) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("create_file");
-
- {
- File file(file_path, base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_ASYNC);
- EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file.async());
- }
-
- {
- File file(file_path, base::File::FLAG_OPEN_ALWAYS);
- EXPECT_TRUE(file.IsValid());
- EXPECT_FALSE(file.async());
- }
-}
-
-TEST(FileTest, DeleteOpenFile) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("create_file_1");
-
- // Create a file.
- File file(file_path,
- base::File::FLAG_OPEN_ALWAYS | base::File::FLAG_READ |
- base::File::FLAG_SHARE_DELETE);
- EXPECT_TRUE(file.IsValid());
- EXPECT_TRUE(file.created());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
-
- // Open an existing file and mark it as delete on close.
- File same_file(file_path,
- base::File::FLAG_OPEN | base::File::FLAG_DELETE_ON_CLOSE |
- base::File::FLAG_READ);
- EXPECT_TRUE(file.IsValid());
- EXPECT_FALSE(same_file.created());
- EXPECT_EQ(base::File::FILE_OK, same_file.error_details());
-
- // Close both handles and check that the file is gone.
- file.Close();
- same_file.Close();
- EXPECT_FALSE(base::PathExists(file_path));
-}
-
-TEST(FileTest, ReadWrite) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("read_write_file");
- File file(file_path,
- base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE);
- ASSERT_TRUE(file.IsValid());
-
- char data_to_write[] = "test";
- const int kTestDataSize = 4;
-
- // Write 0 bytes to the file.
- int bytes_written = file.Write(0, data_to_write, 0);
- EXPECT_EQ(0, bytes_written);
-
- // Write 0 bytes, with buf=nullptr.
- bytes_written = file.Write(0, nullptr, 0);
- EXPECT_EQ(0, bytes_written);
-
- // Write "test" to the file.
- bytes_written = file.Write(0, data_to_write, kTestDataSize);
- EXPECT_EQ(kTestDataSize, bytes_written);
-
- // Read from EOF.
- char data_read_1[32];
- int bytes_read = file.Read(kTestDataSize, data_read_1, kTestDataSize);
- EXPECT_EQ(0, bytes_read);
-
- // Read from somewhere in the middle of the file.
- const int kPartialReadOffset = 1;
- bytes_read = file.Read(kPartialReadOffset, data_read_1, kTestDataSize);
- EXPECT_EQ(kTestDataSize - kPartialReadOffset, bytes_read);
- for (int i = 0; i < bytes_read; i++)
- EXPECT_EQ(data_to_write[i + kPartialReadOffset], data_read_1[i]);
-
- // Read 0 bytes.
- bytes_read = file.Read(0, data_read_1, 0);
- EXPECT_EQ(0, bytes_read);
-
- // Read the entire file.
- bytes_read = file.Read(0, data_read_1, kTestDataSize);
- EXPECT_EQ(kTestDataSize, bytes_read);
- for (int i = 0; i < bytes_read; i++)
- EXPECT_EQ(data_to_write[i], data_read_1[i]);
-
- // Read again, but using the trivial native wrapper.
- bytes_read = file.ReadNoBestEffort(0, data_read_1, kTestDataSize);
- EXPECT_LE(bytes_read, kTestDataSize);
- for (int i = 0; i < bytes_read; i++)
- EXPECT_EQ(data_to_write[i], data_read_1[i]);
-
- // Write past the end of the file.
- const int kOffsetBeyondEndOfFile = 10;
- const int kPartialWriteLength = 2;
- bytes_written = file.Write(kOffsetBeyondEndOfFile,
- data_to_write, kPartialWriteLength);
- EXPECT_EQ(kPartialWriteLength, bytes_written);
-
- // Make sure the file was extended.
- int64_t file_size = 0;
- EXPECT_TRUE(GetFileSize(file_path, &file_size));
- EXPECT_EQ(kOffsetBeyondEndOfFile + kPartialWriteLength, file_size);
-
- // Make sure the file was zero-padded.
- char data_read_2[32];
- bytes_read = file.Read(0, data_read_2, static_cast<int>(file_size));
- EXPECT_EQ(file_size, bytes_read);
- for (int i = 0; i < kTestDataSize; i++)
- EXPECT_EQ(data_to_write[i], data_read_2[i]);
- for (int i = kTestDataSize; i < kOffsetBeyondEndOfFile; i++)
- EXPECT_EQ(0, data_read_2[i]);
- for (int i = kOffsetBeyondEndOfFile; i < file_size; i++)
- EXPECT_EQ(data_to_write[i - kOffsetBeyondEndOfFile], data_read_2[i]);
-}
-
-TEST(FileTest, GetLastFileError) {
-#if defined(OS_WIN)
- ::SetLastError(ERROR_ACCESS_DENIED);
-#else
- errno = EACCES;
-#endif
- EXPECT_EQ(File::FILE_ERROR_ACCESS_DENIED, File::GetLastFileError());
-
- base::ScopedTempDir temp_dir;
- EXPECT_TRUE(temp_dir.CreateUniqueTempDir());
-
- FilePath nonexistent_path(temp_dir.GetPath().AppendASCII("nonexistent"));
- File file(nonexistent_path, File::FLAG_OPEN | File::FLAG_READ);
- File::Error last_error = File::GetLastFileError();
- EXPECT_FALSE(file.IsValid());
- EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, file.error_details());
- EXPECT_EQ(File::FILE_ERROR_NOT_FOUND, last_error);
-}
-
-TEST(FileTest, Append) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("append_file");
- File file(file_path, base::File::FLAG_CREATE | base::File::FLAG_APPEND);
- ASSERT_TRUE(file.IsValid());
-
- char data_to_write[] = "test";
- const int kTestDataSize = 4;
-
- // Write 0 bytes to the file.
- int bytes_written = file.Write(0, data_to_write, 0);
- EXPECT_EQ(0, bytes_written);
-
- // Write 0 bytes, with buf=nullptr.
- bytes_written = file.Write(0, nullptr, 0);
- EXPECT_EQ(0, bytes_written);
-
- // Write "test" to the file.
- bytes_written = file.Write(0, data_to_write, kTestDataSize);
- EXPECT_EQ(kTestDataSize, bytes_written);
-
- file.Close();
- File file2(file_path,
- base::File::FLAG_OPEN | base::File::FLAG_READ |
- base::File::FLAG_APPEND);
- ASSERT_TRUE(file2.IsValid());
-
- // Test passing the file around.
- file = std::move(file2);
- EXPECT_FALSE(file2.IsValid());
- ASSERT_TRUE(file.IsValid());
-
- char append_data_to_write[] = "78";
- const int kAppendDataSize = 2;
-
- // Append "78" to the file.
- bytes_written = file.Write(0, append_data_to_write, kAppendDataSize);
- EXPECT_EQ(kAppendDataSize, bytes_written);
-
- // Read the entire file.
- char data_read_1[32];
- int bytes_read = file.Read(0, data_read_1,
- kTestDataSize + kAppendDataSize);
- EXPECT_EQ(kTestDataSize + kAppendDataSize, bytes_read);
- for (int i = 0; i < kTestDataSize; i++)
- EXPECT_EQ(data_to_write[i], data_read_1[i]);
- for (int i = 0; i < kAppendDataSize; i++)
- EXPECT_EQ(append_data_to_write[i], data_read_1[kTestDataSize + i]);
-}
-
-
-TEST(FileTest, Length) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("truncate_file");
- File file(file_path,
- base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE);
- ASSERT_TRUE(file.IsValid());
- EXPECT_EQ(0, file.GetLength());
-
- // Write "test" to the file.
- char data_to_write[] = "test";
- int kTestDataSize = 4;
- int bytes_written = file.Write(0, data_to_write, kTestDataSize);
- EXPECT_EQ(kTestDataSize, bytes_written);
-
- // Extend the file.
- const int kExtendedFileLength = 10;
- int64_t file_size = 0;
- EXPECT_TRUE(file.SetLength(kExtendedFileLength));
- EXPECT_EQ(kExtendedFileLength, file.GetLength());
- EXPECT_TRUE(GetFileSize(file_path, &file_size));
- EXPECT_EQ(kExtendedFileLength, file_size);
-
- // Make sure the file was zero-padded.
- char data_read[32];
- int bytes_read = file.Read(0, data_read, static_cast<int>(file_size));
- EXPECT_EQ(file_size, bytes_read);
- for (int i = 0; i < kTestDataSize; i++)
- EXPECT_EQ(data_to_write[i], data_read[i]);
- for (int i = kTestDataSize; i < file_size; i++)
- EXPECT_EQ(0, data_read[i]);
-
- // Truncate the file.
- const int kTruncatedFileLength = 2;
- EXPECT_TRUE(file.SetLength(kTruncatedFileLength));
- EXPECT_EQ(kTruncatedFileLength, file.GetLength());
- EXPECT_TRUE(GetFileSize(file_path, &file_size));
- EXPECT_EQ(kTruncatedFileLength, file_size);
-
- // Make sure the file was truncated.
- bytes_read = file.Read(0, data_read, kTestDataSize);
- EXPECT_EQ(file_size, bytes_read);
- for (int i = 0; i < file_size; i++)
- EXPECT_EQ(data_to_write[i], data_read[i]);
-
- // Close the file and reopen with base::File::FLAG_CREATE_ALWAYS, and make
- // sure the file is empty (old file was overridden).
- file.Close();
- file.Initialize(file_path,
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- EXPECT_EQ(0, file.GetLength());
-}
-
-// Flakily fails: http://crbug.com/86494
-#if defined(OS_ANDROID)
-TEST(FileTest, TouchGetInfo) {
-#else
-TEST(FileTest, DISABLED_TouchGetInfo) {
-#endif
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- File file(temp_dir.GetPath().AppendASCII("touch_get_info_file"),
- base::File::FLAG_CREATE | base::File::FLAG_WRITE |
- base::File::FLAG_WRITE_ATTRIBUTES);
- ASSERT_TRUE(file.IsValid());
-
- // Get info for a newly created file.
- base::File::Info info;
- EXPECT_TRUE(file.GetInfo(&info));
-
- // Add 2 seconds to account for possible rounding errors on
- // filesystems that use a 1s or 2s timestamp granularity.
- base::Time now = base::Time::Now() + base::TimeDelta::FromSeconds(2);
- EXPECT_EQ(0, info.size);
- EXPECT_FALSE(info.is_directory);
- EXPECT_FALSE(info.is_symbolic_link);
- EXPECT_LE(info.last_accessed.ToInternalValue(), now.ToInternalValue());
- EXPECT_LE(info.last_modified.ToInternalValue(), now.ToInternalValue());
- EXPECT_LE(info.creation_time.ToInternalValue(), now.ToInternalValue());
- base::Time creation_time = info.creation_time;
-
- // Write "test" to the file.
- char data[] = "test";
- const int kTestDataSize = 4;
- int bytes_written = file.Write(0, data, kTestDataSize);
- EXPECT_EQ(kTestDataSize, bytes_written);
-
- // Change the last_accessed and last_modified dates.
- // It's best to add values that are multiples of 2 (in seconds)
- // to the current last_accessed and last_modified times, because
- // FATxx uses a 2s timestamp granularity.
- base::Time new_last_accessed =
- info.last_accessed + base::TimeDelta::FromSeconds(234);
- base::Time new_last_modified =
- info.last_modified + base::TimeDelta::FromMinutes(567);
-
- EXPECT_TRUE(file.SetTimes(new_last_accessed, new_last_modified));
-
- // Make sure the file info was updated accordingly.
- EXPECT_TRUE(file.GetInfo(&info));
- EXPECT_EQ(info.size, kTestDataSize);
- EXPECT_FALSE(info.is_directory);
- EXPECT_FALSE(info.is_symbolic_link);
-
- // ext2/ext3 and HPS/HPS+ seem to have a timestamp granularity of 1s.
-#if defined(OS_POSIX)
- EXPECT_EQ(info.last_accessed.ToTimeVal().tv_sec,
- new_last_accessed.ToTimeVal().tv_sec);
- EXPECT_EQ(info.last_modified.ToTimeVal().tv_sec,
- new_last_modified.ToTimeVal().tv_sec);
-#else
- EXPECT_EQ(info.last_accessed.ToInternalValue(),
- new_last_accessed.ToInternalValue());
- EXPECT_EQ(info.last_modified.ToInternalValue(),
- new_last_modified.ToInternalValue());
-#endif
-
- EXPECT_EQ(info.creation_time.ToInternalValue(),
- creation_time.ToInternalValue());
-}
-
-TEST(FileTest, ReadAtCurrentPosition) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path =
- temp_dir.GetPath().AppendASCII("read_at_current_position");
- File file(file_path,
- base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
-
- const char kData[] = "test";
- const int kDataSize = sizeof(kData) - 1;
- EXPECT_EQ(kDataSize, file.Write(0, kData, kDataSize));
-
- EXPECT_EQ(0, file.Seek(base::File::FROM_BEGIN, 0));
-
- char buffer[kDataSize];
- int first_chunk_size = kDataSize / 2;
- EXPECT_EQ(first_chunk_size, file.ReadAtCurrentPos(buffer, first_chunk_size));
- EXPECT_EQ(kDataSize - first_chunk_size,
- file.ReadAtCurrentPos(buffer + first_chunk_size,
- kDataSize - first_chunk_size));
- EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
-}
-
-TEST(FileTest, WriteAtCurrentPosition) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path =
- temp_dir.GetPath().AppendASCII("write_at_current_position");
- File file(file_path,
- base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
-
- const char kData[] = "test";
- const int kDataSize = sizeof(kData) - 1;
-
- int first_chunk_size = kDataSize / 2;
- EXPECT_EQ(first_chunk_size, file.WriteAtCurrentPos(kData, first_chunk_size));
- EXPECT_EQ(kDataSize - first_chunk_size,
- file.WriteAtCurrentPos(kData + first_chunk_size,
- kDataSize - first_chunk_size));
-
- char buffer[kDataSize];
- EXPECT_EQ(kDataSize, file.Read(0, buffer, kDataSize));
- EXPECT_EQ(std::string(buffer, buffer + kDataSize), std::string(kData));
-}
-
-TEST(FileTest, Seek) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("seek_file");
- File file(file_path,
- base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE);
- ASSERT_TRUE(file.IsValid());
-
- const int64_t kOffset = 10;
- EXPECT_EQ(kOffset, file.Seek(base::File::FROM_BEGIN, kOffset));
- EXPECT_EQ(2 * kOffset, file.Seek(base::File::FROM_CURRENT, kOffset));
- EXPECT_EQ(kOffset, file.Seek(base::File::FROM_CURRENT, -kOffset));
- EXPECT_TRUE(file.SetLength(kOffset * 2));
- EXPECT_EQ(kOffset, file.Seek(base::File::FROM_END, -kOffset));
-}
-
-TEST(FileTest, Duplicate) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
- File file(file_path,(base::File::FLAG_CREATE |
- base::File::FLAG_READ |
- base::File::FLAG_WRITE));
- ASSERT_TRUE(file.IsValid());
-
- File file2(file.Duplicate());
- ASSERT_TRUE(file2.IsValid());
-
- // Write through one handle, close it, read through the other.
- static const char kData[] = "now is a good time.";
- static const int kDataLen = sizeof(kData) - 1;
-
- ASSERT_EQ(0, file.Seek(base::File::FROM_CURRENT, 0));
- ASSERT_EQ(0, file2.Seek(base::File::FROM_CURRENT, 0));
- ASSERT_EQ(kDataLen, file.WriteAtCurrentPos(kData, kDataLen));
- ASSERT_EQ(kDataLen, file.Seek(base::File::FROM_CURRENT, 0));
- ASSERT_EQ(kDataLen, file2.Seek(base::File::FROM_CURRENT, 0));
- file.Close();
- char buf[kDataLen];
- ASSERT_EQ(kDataLen, file2.Read(0, &buf[0], kDataLen));
- ASSERT_EQ(std::string(kData, kDataLen), std::string(&buf[0], kDataLen));
-}
-
-TEST(FileTest, DuplicateDeleteOnClose) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
- File file(file_path,(base::File::FLAG_CREATE |
- base::File::FLAG_READ |
- base::File::FLAG_WRITE |
- base::File::FLAG_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
- File file2(file.Duplicate());
- ASSERT_TRUE(file2.IsValid());
- file.Close();
- file2.Close();
- ASSERT_FALSE(base::PathExists(file_path));
-}
-
-#if defined(OS_WIN)
-TEST(FileTest, GetInfoForDirectory) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath empty_dir =
- temp_dir.GetPath().Append(FILE_PATH_LITERAL("gpfi_test"));
- ASSERT_TRUE(CreateDirectory(empty_dir));
-
- base::File dir(
- ::CreateFile(empty_dir.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));
- ASSERT_TRUE(dir.IsValid());
-
- base::File::Info info;
- EXPECT_TRUE(dir.GetInfo(&info));
- EXPECT_TRUE(info.is_directory);
- EXPECT_FALSE(info.is_symbolic_link);
- EXPECT_EQ(0, info.size);
-}
-
-TEST(FileTest, DeleteNoop) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // Creating and closing a file with DELETE perms should do nothing special.
- File file(file_path,
- (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
- file.Close();
- ASSERT_TRUE(base::PathExists(file_path));
-}
-
-TEST(FileTest, Delete) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // Creating a file with DELETE and then marking for delete on close should
- // delete it.
- File file(file_path,
- (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
- ASSERT_TRUE(file.DeleteOnClose(true));
- file.Close();
- ASSERT_FALSE(base::PathExists(file_path));
-}
-
-TEST(FileTest, DeleteThenRevoke) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // Creating a file with DELETE, marking it for delete, then clearing delete on
- // close should not delete it.
- File file(file_path,
- (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
- ASSERT_TRUE(file.DeleteOnClose(true));
- ASSERT_TRUE(file.DeleteOnClose(false));
- file.Close();
- ASSERT_TRUE(base::PathExists(file_path));
-}
-
-TEST(FileTest, IrrevokableDeleteOnClose) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // DELETE_ON_CLOSE cannot be revoked by this opener.
- File file(
- file_path,
- (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
- base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
- // https://msdn.microsoft.com/library/windows/desktop/aa364221.aspx says that
- // setting the dispositon has no effect if the handle was opened with
- // FLAG_DELETE_ON_CLOSE. Do not make the test's success dependent on whether
- // or not SetFileInformationByHandle indicates success or failure. (It happens
- // to indicate success on Windows 10.)
- file.DeleteOnClose(false);
- file.Close();
- ASSERT_FALSE(base::PathExists(file_path));
-}
-
-TEST(FileTest, IrrevokableDeleteOnCloseOther) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // DELETE_ON_CLOSE cannot be revoked by another opener.
- File file(
- file_path,
- (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE | base::File::FLAG_DELETE_ON_CLOSE |
- base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
-
- File file2(
- file_path,
- (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
- base::File::FLAG_SHARE_DELETE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file2.IsValid());
-
- file2.DeleteOnClose(false);
- file2.Close();
- ASSERT_TRUE(base::PathExists(file_path));
- file.Close();
- ASSERT_FALSE(base::PathExists(file_path));
-}
-
-TEST(FileTest, DeleteWithoutPermission) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // It should not be possible to mark a file for deletion when it was not
- // created/opened with DELETE.
- File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE));
- ASSERT_TRUE(file.IsValid());
- ASSERT_FALSE(file.DeleteOnClose(true));
- file.Close();
- ASSERT_TRUE(base::PathExists(file_path));
-}
-
-TEST(FileTest, UnsharedDeleteOnClose) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // Opening with DELETE_ON_CLOSE when a previous opener hasn't enabled sharing
- // will fail.
- File file(file_path, (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE));
- ASSERT_TRUE(file.IsValid());
- File file2(
- file_path,
- (base::File::FLAG_OPEN | base::File::FLAG_READ | base::File::FLAG_WRITE |
- base::File::FLAG_DELETE_ON_CLOSE | base::File::FLAG_SHARE_DELETE));
- ASSERT_FALSE(file2.IsValid());
-
- file.Close();
- ASSERT_TRUE(base::PathExists(file_path));
-}
-
-TEST(FileTest, NoDeleteOnCloseWithMappedFile) {
- base::ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("file");
-
- // Mapping a file into memory blocks DeleteOnClose.
- File file(file_path,
- (base::File::FLAG_CREATE | base::File::FLAG_READ |
- base::File::FLAG_WRITE | base::File::FLAG_CAN_DELETE_ON_CLOSE));
- ASSERT_TRUE(file.IsValid());
- ASSERT_EQ(5, file.WriteAtCurrentPos("12345", 5));
-
- {
- base::MemoryMappedFile mapping;
- ASSERT_TRUE(mapping.Initialize(file.Duplicate()));
- ASSERT_EQ(5U, mapping.length());
-
- EXPECT_FALSE(file.DeleteOnClose(true));
- }
-
- file.Close();
- ASSERT_TRUE(base::PathExists(file_path));
-}
-#endif // defined(OS_WIN)
diff --git a/base/files/file_util_unittest.cc b/base/files/file_util_unittest.cc
deleted file mode 100644
index b4de085..0000000
--- a/base/files/file_util_unittest.cc
+++ /dev/null
@@ -1,3683 +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 <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/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 "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));
- }
-}
-
-TEST_F(FileUtilTest, 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) && !defined(OS_FUCHSIA)
-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));
-#if defined(OS_ANDROID)
- EXPECT_EQ("Pr", data);
-#else
- EXPECT_EQ("pr", data);
-#endif
-
- data = "temp";
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, &data, 4));
-#if defined(OS_ANDROID)
- EXPECT_EQ("Proc", data);
-#else
- EXPECT_EQ("proc", data);
-#endif
-
- EXPECT_FALSE(ReadFileToStringWithMaxSize(file_path, nullptr, 4));
-}
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-
-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
-
-#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/important_file_writer_unittest.cc b/base/files/important_file_writer_unittest.cc
deleted file mode 100644
index 493fb36..0000000
--- a/base/files/important_file_writer_unittest.cc
+++ /dev/null
@@ -1,351 +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/important_file_writer.h"
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/location.h"
-#include "base/logging.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/single_thread_task_runner.h"
-#include "base/test/histogram_tester.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "base/timer/mock_timer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-std::string GetFileContent(const FilePath& path) {
- std::string content;
- if (!ReadFileToString(path, &content)) {
- NOTREACHED();
- }
- return content;
-}
-
-class DataSerializer : public ImportantFileWriter::DataSerializer {
- public:
- explicit DataSerializer(const std::string& data) : data_(data) {
- }
-
- bool SerializeData(std::string* output) override {
- output->assign(data_);
- return true;
- }
-
- private:
- const std::string data_;
-};
-
-class FailingDataSerializer : public ImportantFileWriter::DataSerializer {
- public:
- bool SerializeData(std::string* output) override { return false; }
-};
-
-enum WriteCallbackObservationState {
- NOT_CALLED,
- CALLED_WITH_ERROR,
- CALLED_WITH_SUCCESS,
-};
-
-class WriteCallbacksObserver {
- public:
- WriteCallbacksObserver() = default;
-
- // Register OnBeforeWrite() and OnAfterWrite() to be called on the next write
- // of |writer|.
- void ObserveNextWriteCallbacks(ImportantFileWriter* writer);
-
- // Returns the |WriteCallbackObservationState| which was observed, then resets
- // it to |NOT_CALLED|.
- WriteCallbackObservationState GetAndResetObservationState();
-
- private:
- void OnBeforeWrite() {
- EXPECT_FALSE(before_write_called_);
- before_write_called_ = true;
- }
-
- void OnAfterWrite(bool success) {
- EXPECT_EQ(NOT_CALLED, after_write_observation_state_);
- after_write_observation_state_ =
- success ? CALLED_WITH_SUCCESS : CALLED_WITH_ERROR;
- }
-
- bool before_write_called_ = false;
- WriteCallbackObservationState after_write_observation_state_ = NOT_CALLED;
-
- DISALLOW_COPY_AND_ASSIGN(WriteCallbacksObserver);
-};
-
-void WriteCallbacksObserver::ObserveNextWriteCallbacks(
- ImportantFileWriter* writer) {
- writer->RegisterOnNextWriteCallbacks(
- base::Bind(&WriteCallbacksObserver::OnBeforeWrite,
- base::Unretained(this)),
- base::Bind(&WriteCallbacksObserver::OnAfterWrite,
- base::Unretained(this)));
-}
-
-WriteCallbackObservationState
-WriteCallbacksObserver::GetAndResetObservationState() {
- EXPECT_EQ(after_write_observation_state_ != NOT_CALLED, before_write_called_)
- << "The before-write callback should always be called before the "
- "after-write callback";
-
- WriteCallbackObservationState state = after_write_observation_state_;
- before_write_called_ = false;
- after_write_observation_state_ = NOT_CALLED;
- return state;
-}
-
-} // namespace
-
-class ImportantFileWriterTest : public testing::Test {
- public:
- ImportantFileWriterTest() = default;
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- file_ = temp_dir_.GetPath().AppendASCII("test-file");
- }
-
- protected:
- WriteCallbacksObserver write_callback_observer_;
- FilePath file_;
- MessageLoop loop_;
-
- private:
- ScopedTempDir temp_dir_;
-};
-
-TEST_F(ImportantFileWriterTest, Basic) {
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- EXPECT_FALSE(PathExists(writer.path()));
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
- writer.WriteNow(std::make_unique<std::string>("foo"));
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("foo", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, WriteWithObserver) {
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- EXPECT_FALSE(PathExists(writer.path()));
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
-
- // Confirm that the observer is invoked.
- write_callback_observer_.ObserveNextWriteCallbacks(&writer);
- writer.WriteNow(std::make_unique<std::string>("foo"));
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(CALLED_WITH_SUCCESS,
- write_callback_observer_.GetAndResetObservationState());
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("foo", GetFileContent(writer.path()));
-
- // Confirm that re-installing the observer works for another write.
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
- write_callback_observer_.ObserveNextWriteCallbacks(&writer);
- writer.WriteNow(std::make_unique<std::string>("bar"));
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(CALLED_WITH_SUCCESS,
- write_callback_observer_.GetAndResetObservationState());
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("bar", GetFileContent(writer.path()));
-
- // Confirm that writing again without re-installing the observer doesn't
- // result in a notification.
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
- writer.WriteNow(std::make_unique<std::string>("baz"));
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("baz", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, FailedWriteWithObserver) {
- // Use an invalid file path (relative paths are invalid) to get a
- // FILE_ERROR_ACCESS_DENIED error when trying to write the file.
- ImportantFileWriter writer(FilePath().AppendASCII("bad/../path"),
- ThreadTaskRunnerHandle::Get());
- EXPECT_FALSE(PathExists(writer.path()));
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
- write_callback_observer_.ObserveNextWriteCallbacks(&writer);
- writer.WriteNow(std::make_unique<std::string>("foo"));
- RunLoop().RunUntilIdle();
-
- // Confirm that the write observer was invoked with its boolean parameter set
- // to false.
- EXPECT_EQ(CALLED_WITH_ERROR,
- write_callback_observer_.GetAndResetObservationState());
- EXPECT_FALSE(PathExists(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, CallbackRunsOnWriterThread) {
- base::Thread file_writer_thread("ImportantFileWriter test thread");
- file_writer_thread.Start();
- ImportantFileWriter writer(file_, file_writer_thread.task_runner());
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
-
- // Block execution on |file_writer_thread| to verify that callbacks are
- // executed on it.
- base::WaitableEvent wait_helper(
- base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- file_writer_thread.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&base::WaitableEvent::Wait,
- base::Unretained(&wait_helper)));
-
- write_callback_observer_.ObserveNextWriteCallbacks(&writer);
- writer.WriteNow(std::make_unique<std::string>("foo"));
- RunLoop().RunUntilIdle();
-
- // Expect the callback to not have been executed before the
- // |file_writer_thread| is unblocked.
- EXPECT_EQ(NOT_CALLED, write_callback_observer_.GetAndResetObservationState());
-
- wait_helper.Signal();
- file_writer_thread.FlushForTesting();
-
- EXPECT_EQ(CALLED_WITH_SUCCESS,
- write_callback_observer_.GetAndResetObservationState());
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("foo", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, ScheduleWrite) {
- constexpr TimeDelta kCommitInterval = TimeDelta::FromSeconds(12345);
- MockTimer timer(true, false);
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get(),
- kCommitInterval);
- writer.SetTimerForTesting(&timer);
- EXPECT_FALSE(writer.HasPendingWrite());
- DataSerializer serializer("foo");
- writer.ScheduleWrite(&serializer);
- EXPECT_TRUE(writer.HasPendingWrite());
- ASSERT_TRUE(timer.IsRunning());
- EXPECT_EQ(kCommitInterval, timer.GetCurrentDelay());
- timer.Fire();
- EXPECT_FALSE(writer.HasPendingWrite());
- EXPECT_FALSE(timer.IsRunning());
- RunLoop().RunUntilIdle();
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("foo", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, DoScheduledWrite) {
- MockTimer timer(true, false);
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- writer.SetTimerForTesting(&timer);
- EXPECT_FALSE(writer.HasPendingWrite());
- DataSerializer serializer("foo");
- writer.ScheduleWrite(&serializer);
- EXPECT_TRUE(writer.HasPendingWrite());
- writer.DoScheduledWrite();
- EXPECT_FALSE(writer.HasPendingWrite());
- RunLoop().RunUntilIdle();
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("foo", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, BatchingWrites) {
- MockTimer timer(true, false);
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- writer.SetTimerForTesting(&timer);
- DataSerializer foo("foo"), bar("bar"), baz("baz");
- writer.ScheduleWrite(&foo);
- writer.ScheduleWrite(&bar);
- writer.ScheduleWrite(&baz);
- ASSERT_TRUE(timer.IsRunning());
- timer.Fire();
- RunLoop().RunUntilIdle();
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("baz", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, ScheduleWrite_FailToSerialize) {
- MockTimer timer(true, false);
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- writer.SetTimerForTesting(&timer);
- EXPECT_FALSE(writer.HasPendingWrite());
- FailingDataSerializer serializer;
- writer.ScheduleWrite(&serializer);
- EXPECT_TRUE(writer.HasPendingWrite());
- ASSERT_TRUE(timer.IsRunning());
- timer.Fire();
- EXPECT_FALSE(writer.HasPendingWrite());
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(PathExists(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, ScheduleWrite_WriteNow) {
- MockTimer timer(true, false);
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- writer.SetTimerForTesting(&timer);
- EXPECT_FALSE(writer.HasPendingWrite());
- DataSerializer serializer("foo");
- writer.ScheduleWrite(&serializer);
- EXPECT_TRUE(writer.HasPendingWrite());
- writer.WriteNow(std::make_unique<std::string>("bar"));
- EXPECT_FALSE(writer.HasPendingWrite());
- EXPECT_FALSE(timer.IsRunning());
-
- RunLoop().RunUntilIdle();
- ASSERT_TRUE(PathExists(writer.path()));
- EXPECT_EQ("bar", GetFileContent(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, DoScheduledWrite_FailToSerialize) {
- MockTimer timer(true, false);
- ImportantFileWriter writer(file_, ThreadTaskRunnerHandle::Get());
- writer.SetTimerForTesting(&timer);
- EXPECT_FALSE(writer.HasPendingWrite());
- FailingDataSerializer serializer;
- writer.ScheduleWrite(&serializer);
- EXPECT_TRUE(writer.HasPendingWrite());
-
- writer.DoScheduledWrite();
- EXPECT_FALSE(timer.IsRunning());
- EXPECT_FALSE(writer.HasPendingWrite());
- RunLoop().RunUntilIdle();
- EXPECT_FALSE(PathExists(writer.path()));
-}
-
-TEST_F(ImportantFileWriterTest, WriteFileAtomicallyHistogramSuffixTest) {
- base::HistogramTester histogram_tester;
- EXPECT_FALSE(PathExists(file_));
- EXPECT_TRUE(ImportantFileWriter::WriteFileAtomically(file_, "baz", "test"));
- EXPECT_TRUE(PathExists(file_));
- EXPECT_EQ("baz", GetFileContent(file_));
- histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError", 0);
- histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError.test", 0);
-
- FilePath invalid_file_ = FilePath().AppendASCII("bad/../non_existent/path");
- EXPECT_FALSE(PathExists(invalid_file_));
- EXPECT_FALSE(
- ImportantFileWriter::WriteFileAtomically(invalid_file_, nullptr));
- histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError", 1);
- histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError.test", 0);
- EXPECT_FALSE(
- ImportantFileWriter::WriteFileAtomically(invalid_file_, nullptr, "test"));
- histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError", 1);
- histogram_tester.ExpectTotalCount("ImportantFile.FileCreateError.test", 1);
-}
-
-} // 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 b7acc61..0000000
--- 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/files/scoped_temp_dir_unittest.cc b/base/files/scoped_temp_dir_unittest.cc
deleted file mode 100644
index 84eff6e..0000000
--- a/base/files/scoped_temp_dir_unittest.cc
+++ /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.
-
-#include <string>
-
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(ScopedTempDir, FullPath) {
- FilePath test_path;
- base::CreateNewTempDirectory(FILE_PATH_LITERAL("scoped_temp_dir"),
- &test_path);
-
- // Against an existing dir, it should get destroyed when leaving scope.
- EXPECT_TRUE(DirectoryExists(test_path));
- {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.Set(test_path));
- EXPECT_TRUE(dir.IsValid());
- }
- EXPECT_FALSE(DirectoryExists(test_path));
-
- {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.Set(test_path));
- // Now the dir doesn't exist, so ensure that it gets created.
- EXPECT_TRUE(DirectoryExists(test_path));
- // When we call Release(), it shouldn't get destroyed when leaving scope.
- FilePath path = dir.Take();
- EXPECT_EQ(path.value(), test_path.value());
- EXPECT_FALSE(dir.IsValid());
- }
- EXPECT_TRUE(DirectoryExists(test_path));
-
- // Clean up.
- {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.Set(test_path));
- }
- EXPECT_FALSE(DirectoryExists(test_path));
-}
-
-TEST(ScopedTempDir, TempDir) {
- // In this case, just verify that a directory was created and that it's a
- // child of TempDir.
- FilePath test_path;
- {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.CreateUniqueTempDir());
- test_path = dir.GetPath();
- EXPECT_TRUE(DirectoryExists(test_path));
- FilePath tmp_dir;
- EXPECT_TRUE(base::GetTempDir(&tmp_dir));
- EXPECT_TRUE(test_path.value().find(tmp_dir.value()) != std::string::npos);
- }
- EXPECT_FALSE(DirectoryExists(test_path));
-}
-
-TEST(ScopedTempDir, UniqueTempDirUnderPath) {
- // Create a path which will contain a unique temp path.
- FilePath base_path;
- ASSERT_TRUE(base::CreateNewTempDirectory(FILE_PATH_LITERAL("base_dir"),
- &base_path));
-
- FilePath test_path;
- {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.CreateUniqueTempDirUnderPath(base_path));
- test_path = dir.GetPath();
- EXPECT_TRUE(DirectoryExists(test_path));
- EXPECT_TRUE(base_path.IsParent(test_path));
- EXPECT_TRUE(test_path.value().find(base_path.value()) != std::string::npos);
- }
- EXPECT_FALSE(DirectoryExists(test_path));
- base::DeleteFile(base_path, true);
-}
-
-TEST(ScopedTempDir, MultipleInvocations) {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.CreateUniqueTempDir());
- EXPECT_FALSE(dir.CreateUniqueTempDir());
- EXPECT_TRUE(dir.Delete());
- EXPECT_TRUE(dir.CreateUniqueTempDir());
- EXPECT_FALSE(dir.CreateUniqueTempDir());
- ScopedTempDir other_dir;
- EXPECT_TRUE(other_dir.Set(dir.Take()));
- EXPECT_TRUE(dir.CreateUniqueTempDir());
- EXPECT_FALSE(dir.CreateUniqueTempDir());
- EXPECT_FALSE(other_dir.CreateUniqueTempDir());
-}
-
-#if defined(OS_WIN)
-TEST(ScopedTempDir, LockedTempDir) {
- ScopedTempDir dir;
- EXPECT_TRUE(dir.CreateUniqueTempDir());
- base::File file(dir.GetPath().Append(FILE_PATH_LITERAL("temp")),
- base::File::FLAG_CREATE_ALWAYS | base::File::FLAG_WRITE);
- EXPECT_TRUE(file.IsValid());
- EXPECT_EQ(base::File::FILE_OK, file.error_details());
- EXPECT_FALSE(dir.Delete()); // We should not be able to delete.
- EXPECT_FALSE(dir.GetPath().empty()); // We should still have a valid path.
- file.Close();
- // Now, we should be able to delete.
- EXPECT_TRUE(dir.Delete());
-}
-#endif // defined(OS_WIN)
-
-} // namespace base
diff --git a/base/gmock_unittest.cc b/base/gmock_unittest.cc
deleted file mode 100644
index 5c16728..0000000
--- a/base/gmock_unittest.cc
+++ /dev/null
@@ -1,135 +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.
-//
-// This test is a simple sanity check to make sure gmock is able to build/link
-// correctly. It just instantiates a mock object and runs through a couple of
-// the basic mock features.
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Gmock matchers and actions that we use below.
-using testing::AnyOf;
-using testing::Eq;
-using testing::Return;
-using testing::SetArgPointee;
-using testing::WithArg;
-using testing::_;
-
-namespace {
-
-// Simple class that we can mock out the behavior for. Everything is virtual
-// for easy mocking.
-class SampleClass {
- public:
- SampleClass() = default;
- virtual ~SampleClass() = default;
-
- virtual int ReturnSomething() {
- return -1;
- }
-
- virtual void ReturnNothingConstly() const {
- }
-
- virtual void OutputParam(int* a) {
- }
-
- virtual int ReturnSecond(int a, int b) {
- return b;
- }
-};
-
-// Declare a mock for the class.
-class MockSampleClass : public SampleClass {
- public:
- MOCK_METHOD0(ReturnSomething, int());
- MOCK_CONST_METHOD0(ReturnNothingConstly, void());
- MOCK_METHOD1(OutputParam, void(int* a));
- MOCK_METHOD2(ReturnSecond, int(int a, int b));
-};
-
-// Create a couple of custom actions. Custom actions can be used for adding
-// more complex behavior into your mock...though if you start needing these, ask
-// if you're asking your mock to do too much.
-ACTION(ReturnVal) {
- // Return the first argument received.
- return arg0;
-}
-ACTION(ReturnSecond) {
- // Returns the second argument. This basically implemetns ReturnSecond.
- return arg1;
-}
-
-TEST(GmockTest, SimpleMatchAndActions) {
- // Basic test of some simple gmock matchers, actions, and cardinality
- // expectations.
- MockSampleClass mock;
-
- EXPECT_CALL(mock, ReturnSomething())
- .WillOnce(Return(1))
- .WillOnce(Return(2))
- .WillOnce(Return(3));
- EXPECT_EQ(1, mock.ReturnSomething());
- EXPECT_EQ(2, mock.ReturnSomething());
- EXPECT_EQ(3, mock.ReturnSomething());
-
- EXPECT_CALL(mock, ReturnNothingConstly()).Times(2);
- mock.ReturnNothingConstly();
- mock.ReturnNothingConstly();
-}
-
-TEST(GmockTest, AssignArgument) {
- // Capture an argument for examination.
- MockSampleClass mock;
-
- EXPECT_CALL(mock, OutputParam(_)).WillRepeatedly(SetArgPointee<0>(5));
-
- int arg = 0;
- mock.OutputParam(&arg);
- EXPECT_EQ(5, arg);
-}
-
-TEST(GmockTest, SideEffects) {
- // Capture an argument for examination.
- MockSampleClass mock;
-
- EXPECT_CALL(mock, OutputParam(_)).WillRepeatedly(SetArgPointee<0>(5));
-
- int arg = 0;
- mock.OutputParam(&arg);
- EXPECT_EQ(5, arg);
-}
-
-TEST(GmockTest, CustomAction_ReturnSecond) {
- // Test a mock of the ReturnSecond behavior using an action that provides an
- // alternate implementation of the function. Danger here though, this is
- // starting to add too much behavior of the mock, which means the mock
- // implementation might start to have bugs itself.
- MockSampleClass mock;
-
- EXPECT_CALL(mock, ReturnSecond(_, AnyOf(Eq(4), Eq(5))))
- .WillRepeatedly(ReturnSecond());
- EXPECT_EQ(4, mock.ReturnSecond(-1, 4));
- EXPECT_EQ(5, mock.ReturnSecond(0, 5));
- EXPECT_EQ(4, mock.ReturnSecond(0xdeadbeef, 4));
- EXPECT_EQ(4, mock.ReturnSecond(112358, 4));
- EXPECT_EQ(5, mock.ReturnSecond(1337, 5));
-}
-
-TEST(GmockTest, CustomAction_ReturnVal) {
- // Alternate implemention of ReturnSecond using a more general custom action,
- // and a WithArg adapter to bridge the interfaces.
- MockSampleClass mock;
-
- EXPECT_CALL(mock, ReturnSecond(_, AnyOf(Eq(4), Eq(5))))
- .WillRepeatedly(WithArg<1>(ReturnVal()));
- EXPECT_EQ(4, mock.ReturnSecond(-1, 4));
- EXPECT_EQ(5, mock.ReturnSecond(0, 5));
- EXPECT_EQ(4, mock.ReturnSecond(0xdeadbeef, 4));
- EXPECT_EQ(4, mock.ReturnSecond(112358, 4));
- EXPECT_EQ(5, mock.ReturnSecond(1337, 5));
-}
-
-} // namespace
diff --git a/base/guid_unittest.cc b/base/guid_unittest.cc
deleted file mode 100644
index 8aa56ed..0000000
--- a/base/guid_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/guid.h"
-
-#include <stdint.h>
-
-#include <limits>
-
-#include "base/strings/string_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-bool IsGUIDv4(const std::string& guid) {
- // The format of GUID version 4 must be xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx,
- // where y is one of [8, 9, A, B].
- return IsValidGUID(guid) && guid[14] == '4' &&
- (guid[19] == '8' || guid[19] == '9' || guid[19] == 'A' ||
- guid[19] == 'a' || guid[19] == 'B' || guid[19] == 'b');
-}
-
-} // namespace
-
-TEST(GUIDTest, GUIDGeneratesAllZeroes) {
- uint64_t bytes[] = {0, 0};
- std::string clientid = RandomDataToGUIDString(bytes);
- EXPECT_EQ("00000000-0000-0000-0000-000000000000", clientid);
-}
-
-TEST(GUIDTest, GUIDGeneratesCorrectly) {
- uint64_t bytes[] = {0x0123456789ABCDEFULL, 0xFEDCBA9876543210ULL};
- std::string clientid = RandomDataToGUIDString(bytes);
- EXPECT_EQ("01234567-89ab-cdef-fedc-ba9876543210", clientid);
-}
-
-TEST(GUIDTest, GUIDCorrectlyFormatted) {
- const int kIterations = 10;
- for (int it = 0; it < kIterations; ++it) {
- std::string guid = GenerateGUID();
- EXPECT_TRUE(IsValidGUID(guid));
- EXPECT_TRUE(IsValidGUIDOutputString(guid));
- EXPECT_TRUE(IsValidGUID(ToLowerASCII(guid)));
- EXPECT_TRUE(IsValidGUID(ToUpperASCII(guid)));
- }
-}
-
-TEST(GUIDTest, GUIDBasicUniqueness) {
- const int kIterations = 10;
- for (int it = 0; it < kIterations; ++it) {
- std::string guid1 = GenerateGUID();
- std::string guid2 = GenerateGUID();
- EXPECT_EQ(36U, guid1.length());
- EXPECT_EQ(36U, guid2.length());
- EXPECT_NE(guid1, guid2);
- EXPECT_TRUE(IsGUIDv4(guid1));
- EXPECT_TRUE(IsGUIDv4(guid2));
- }
-}
-
-} // namespace base
diff --git a/base/hash_unittest.cc b/base/hash_unittest.cc
deleted file mode 100644
index fc8a751..0000000
--- 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/bidi_line_iterator_unittest.cc b/base/i18n/bidi_line_iterator_unittest.cc
deleted file mode 100644
index d531313..0000000
--- 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_unittest.cc b/base/i18n/break_iterator_unittest.cc
deleted file mode 100644
index 6137e02..0000000
--- a/base/i18n/break_iterator_unittest.cc
+++ /dev/null
@@ -1,461 +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/stringprintf.h"
-#include "base/strings/utf_string_conversions.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, BreakWide16) {
- // 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, BreakWide32) {
- // 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, 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/case_conversion_unittest.cc b/base/i18n/case_conversion_unittest.cc
deleted file mode 100644
index ee795bc..0000000
--- 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_unittest.cc b/base/i18n/char_iterator_unittest.cc
deleted file mode 100644
index 0cf8e6c..0000000
--- 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_unittest.cc b/base/i18n/character_encoding_unittest.cc
deleted file mode 100644
index 3c11ba3..0000000
--- 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/file_util_icu_unittest.cc b/base/i18n/file_util_icu_unittest.cc
deleted file mode 100644
index f1c2ecc..0000000
--- 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_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/icu_string_conversions_unittest.cc b/base/i18n/icu_string_conversions_unittest.cc
deleted file mode 100644
index 871f18b..0000000
--- 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_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/message_formatter_unittest.cc b/base/i18n/message_formatter_unittest.cc
deleted file mode 100644
index a6f4613..0000000
--- 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_unittest.cc b/base/i18n/number_formatting_unittest.cc
deleted file mode 100644
index 71b15a5..0000000
--- a/base/i18n/number_formatting_unittest.cc
+++ /dev/null
@@ -1,135 +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_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 wchar_t* 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.
- // 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 wchar_t* expected_persian;
- const wchar_t* expected_arabic;
- } cases[] = {
- {0, "0%", L"0\xa0%", L"\x6f0\x66a", L"\x660\x66a\x61c"},
- {42, "42%", L"42\xa0%", L"\x6f4\x6f2\x66a", L"\x664\x662\x66a\x61c"},
- {1024, "1,024%", L"1.024\xa0%", L"\x6f1\x66c\x6f0\x6f2\x6f4\x66a",
- L"\x661\x66c\x660\x662\x664\x66a\x61c"},
- };
-
- 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(WideToUTF16(cases[i].expected_german),
- FormatPercent(cases[i].number));
- i18n::SetICUDefaultLocale("fa");
- EXPECT_EQ(WideToUTF16(cases[i].expected_persian),
- FormatPercent(cases[i].number));
- i18n::SetICUDefaultLocale("ar");
- EXPECT_EQ(WideToUTF16(cases[i].expected_arabic),
- FormatPercent(cases[i].number));
- }
-}
-
-} // namespace
-} // namespace base
diff --git a/base/i18n/rtl_unittest.cc b/base/i18n/rtl_unittest.cc
deleted file mode 100644
index 88ae36a..0000000
--- a/base/i18n/rtl_unittest.cc
+++ /dev/null
@@ -1,567 +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_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 {
-
-namespace {
-
-// A test utility function to set the application default text direction.
-void SetRTL(bool rtl) {
- // Override the current locale/direction.
- SetICUDefaultLocale(rtl ? "he" : "en");
- EXPECT_EQ(rtl, IsRTL());
-}
-
-} // namespace
-
-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).
- SetRTL(!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(<r_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).
- SetRTL(!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).
- SetRTL(!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).
- SetRTL(!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_unittest.cc b/base/i18n/streaming_utf8_validator_unittest.cc
deleted file mode 100644
index f9772d0..0000000
--- 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_search_unittest.cc b/base/i18n/string_search_unittest.cc
deleted file mode 100644
index 69501d6..0000000
--- 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_unittest.cc b/base/i18n/time_formatting_unittest.cc
deleted file mode 100644
index 027b7c9..0000000
--- a/base/i18n/time_formatting_unittest.cc
+++ /dev/null
@@ -1,434 +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) {
- // Test for a locale that uses different mark than "AM" and "PM".
- // As an instance, we use third_party/icu/source/data/locales/de.txt.
- 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 nachm."));
- 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_unittest.cc b/base/i18n/timezone_unittest.cc
deleted file mode 100644
index 57467dc..0000000
--- 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/json/json_parser_unittest.cc b/base/json/json_parser_unittest.cc
deleted file mode 100644
index 0da3db8..0000000
--- a/base/json/json_parser_unittest.cc
+++ /dev/null
@@ -1,462 +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/json/json_parser.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/json/json_reader.h"
-#include "base/memory/ptr_util.h"
-#include "base/optional.h"
-#include "base/strings/stringprintf.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-class JSONParserTest : public testing::Test {
- public:
- JSONParser* NewTestParser(const std::string& input,
- int options = JSON_PARSE_RFC) {
- JSONParser* parser = new JSONParser(options);
- parser->input_ = input;
- parser->index_ = 0;
- return parser;
- }
-
- // MSan will do a better job detecting over-read errors if the input is
- // not nul-terminated on the heap. This will copy |input| to a new buffer
- // owned by |owner|, returning a StringPiece to |owner|.
- StringPiece MakeNotNullTerminatedInput(const char* input,
- std::unique_ptr<char[]>* owner) {
- size_t str_len = strlen(input);
- owner->reset(new char[str_len]);
- memcpy(owner->get(), input, str_len);
- return StringPiece(owner->get(), str_len);
- }
-
- void TestLastThree(JSONParser* parser) {
- EXPECT_EQ(',', *parser->PeekChar());
- parser->ConsumeChar();
- EXPECT_EQ('|', *parser->PeekChar());
- parser->ConsumeChar();
- EXPECT_EQ('\0', *parser->pos());
- EXPECT_EQ(static_cast<size_t>(parser->index_), parser->input_.length());
- }
-};
-
-TEST_F(JSONParserTest, NextChar) {
- std::string input("Hello world");
- std::unique_ptr<JSONParser> parser(NewTestParser(input));
-
- EXPECT_EQ('H', *parser->pos());
- for (size_t i = 1; i < input.length(); ++i) {
- parser->ConsumeChar();
- EXPECT_EQ(input[i], *parser->PeekChar());
- }
- parser->ConsumeChar();
- EXPECT_EQ('\0', *parser->pos());
- EXPECT_EQ(static_cast<size_t>(parser->index_), parser->input_.length());
-}
-
-TEST_F(JSONParserTest, ConsumeString) {
- std::string input("\"test\",|");
- std::unique_ptr<JSONParser> parser(NewTestParser(input));
- Optional<Value> value(parser->ConsumeString());
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- std::string str;
- EXPECT_TRUE(value->GetAsString(&str));
- EXPECT_EQ("test", str);
-}
-
-TEST_F(JSONParserTest, ConsumeList) {
- std::string input("[true, false],|");
- std::unique_ptr<JSONParser> parser(NewTestParser(input));
- Optional<Value> value(parser->ConsumeList());
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- base::ListValue* list;
- EXPECT_TRUE(value->GetAsList(&list));
- EXPECT_EQ(2u, list->GetSize());
-}
-
-TEST_F(JSONParserTest, ConsumeDictionary) {
- std::string input("{\"abc\":\"def\"},|");
- std::unique_ptr<JSONParser> parser(NewTestParser(input));
- Optional<Value> value(parser->ConsumeDictionary());
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- base::DictionaryValue* dict;
- EXPECT_TRUE(value->GetAsDictionary(&dict));
- std::string str;
- EXPECT_TRUE(dict->GetString("abc", &str));
- EXPECT_EQ("def", str);
-}
-
-TEST_F(JSONParserTest, ConsumeLiterals) {
- // Literal |true|.
- std::string input("true,|");
- std::unique_ptr<JSONParser> parser(NewTestParser(input));
- Optional<Value> value(parser->ConsumeLiteral());
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- bool bool_value = false;
- EXPECT_TRUE(value->GetAsBoolean(&bool_value));
- EXPECT_TRUE(bool_value);
-
- // Literal |false|.
- input = "false,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeLiteral();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->GetAsBoolean(&bool_value));
- EXPECT_FALSE(bool_value);
-
- // Literal |null|.
- input = "null,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeLiteral();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->is_none());
-}
-
-TEST_F(JSONParserTest, ConsumeNumbers) {
- // Integer.
- std::string input("1234,|");
- std::unique_ptr<JSONParser> parser(NewTestParser(input));
- Optional<Value> value(parser->ConsumeNumber());
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- int number_i;
- EXPECT_TRUE(value->GetAsInteger(&number_i));
- EXPECT_EQ(1234, number_i);
-
- // Negative integer.
- input = "-1234,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeNumber();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->GetAsInteger(&number_i));
- EXPECT_EQ(-1234, number_i);
-
- // Double.
- input = "12.34,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeNumber();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- double number_d;
- EXPECT_TRUE(value->GetAsDouble(&number_d));
- EXPECT_EQ(12.34, number_d);
-
- // Scientific.
- input = "42e3,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeNumber();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->GetAsDouble(&number_d));
- EXPECT_EQ(42000, number_d);
-
- // Negative scientific.
- input = "314159e-5,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeNumber();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->GetAsDouble(&number_d));
- EXPECT_EQ(3.14159, number_d);
-
- // Positive scientific.
- input = "0.42e+3,|";
- parser.reset(NewTestParser(input));
- value = parser->ConsumeNumber();
- EXPECT_EQ(',', *parser->pos());
-
- TestLastThree(parser.get());
-
- ASSERT_TRUE(value);
- EXPECT_TRUE(value->GetAsDouble(&number_d));
- EXPECT_EQ(420, number_d);
-}
-
-TEST_F(JSONParserTest, ErrorMessages) {
- // Error strings should not be modified in case of success.
- std::string error_message;
- int error_code = 0;
- std::unique_ptr<Value> root = JSONReader::ReadAndReturnError(
- "[42]", JSON_PARSE_RFC, &error_code, &error_message);
- EXPECT_TRUE(error_message.empty());
- EXPECT_EQ(0, error_code);
-
- // Test line and column counting
- const char big_json[] = "[\n0,\n1,\n2,\n3,4,5,6 7,\n8,\n9\n]";
- // error here ----------------------------------^
- root = JSONReader::ReadAndReturnError(big_json, JSON_PARSE_RFC, &error_code,
- &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(5, 10, JSONReader::kSyntaxError),
- error_message);
- EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code);
-
- error_code = 0;
- error_message = "";
- // Test line and column counting with "\r\n" line ending
- const char big_json_crlf[] =
- "[\r\n0,\r\n1,\r\n2,\r\n3,4,5,6 7,\r\n8,\r\n9\r\n]";
- // error here ----------------------^
- root = JSONReader::ReadAndReturnError(big_json_crlf, JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(5, 10, JSONReader::kSyntaxError),
- error_message);
- EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code);
-
- // Test each of the error conditions
- root = JSONReader::ReadAndReturnError("{},{}", JSON_PARSE_RFC, &error_code,
- &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 3,
- JSONReader::kUnexpectedDataAfterRoot), error_message);
- EXPECT_EQ(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, error_code);
-
- std::string nested_json;
- for (int i = 0; i < 201; ++i) {
- nested_json.insert(nested_json.begin(), '[');
- nested_json.append(1, ']');
- }
- root = JSONReader::ReadAndReturnError(nested_json, JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 200, JSONReader::kTooMuchNesting),
- error_message);
- EXPECT_EQ(JSONReader::JSON_TOO_MUCH_NESTING, error_code);
-
- root = JSONReader::ReadAndReturnError("[1,]", JSON_PARSE_RFC, &error_code,
- &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 4, JSONReader::kTrailingComma),
- error_message);
- EXPECT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code);
-
- root = JSONReader::ReadAndReturnError("{foo:\"bar\"}", JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 2,
- JSONReader::kUnquotedDictionaryKey), error_message);
- EXPECT_EQ(JSONReader::JSON_UNQUOTED_DICTIONARY_KEY, error_code);
-
- root = JSONReader::ReadAndReturnError("{\"foo\":\"bar\",}", JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 14, JSONReader::kTrailingComma),
- error_message);
-
- root = JSONReader::ReadAndReturnError("[nu]", JSON_PARSE_RFC, &error_code,
- &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 2, JSONReader::kSyntaxError),
- error_message);
- EXPECT_EQ(JSONReader::JSON_SYNTAX_ERROR, error_code);
-
- root = JSONReader::ReadAndReturnError("[\"xxx\\xq\"]", JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
- error_message);
- EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
-
- root = JSONReader::ReadAndReturnError("[\"xxx\\uq\"]", JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
- error_message);
- EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
-
- root = JSONReader::ReadAndReturnError("[\"xxx\\q\"]", JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_FALSE(root.get());
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 7, JSONReader::kInvalidEscape),
- error_message);
- EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
-
- root = JSONReader::ReadAndReturnError(("[\"\\ufffe\"]"), JSON_PARSE_RFC,
- &error_code, &error_message);
- EXPECT_EQ(JSONParser::FormatErrorMessage(1, 8, JSONReader::kInvalidEscape),
- error_message);
- EXPECT_EQ(JSONReader::JSON_INVALID_ESCAPE, error_code);
-}
-
-TEST_F(JSONParserTest, Decode4ByteUtf8Char) {
- // This test strings contains a 4 byte unicode character (a smiley!) that the
- // reader should be able to handle (the character is \xf0\x9f\x98\x87).
- const char kUtf8Data[] =
- "[\"😇\",[],[],[],{\"google:suggesttype\":[]}]";
- std::string error_message;
- int error_code = 0;
- std::unique_ptr<Value> root = JSONReader::ReadAndReturnError(
- kUtf8Data, JSON_PARSE_RFC, &error_code, &error_message);
- EXPECT_TRUE(root.get()) << error_message;
-}
-
-TEST_F(JSONParserTest, DecodeUnicodeNonCharacter) {
- // Tests Unicode code points (encoded as escaped UTF-16) that are not valid
- // characters.
- EXPECT_FALSE(JSONReader::Read("[\"\\ufdd0\"]"));
- EXPECT_FALSE(JSONReader::Read("[\"\\ufffe\"]"));
- EXPECT_FALSE(JSONReader::Read("[\"\\ud83f\\udffe\"]"));
-
- EXPECT_TRUE(
- JSONReader::Read("[\"\\ufdd0\"]", JSON_REPLACE_INVALID_CHARACTERS));
- EXPECT_TRUE(
- JSONReader::Read("[\"\\ufffe\"]", JSON_REPLACE_INVALID_CHARACTERS));
-}
-
-TEST_F(JSONParserTest, DecodeNegativeEscapeSequence) {
- EXPECT_FALSE(JSONReader::Read("[\"\\x-A\"]"));
- EXPECT_FALSE(JSONReader::Read("[\"\\u-00A\"]"));
-}
-
-// Verifies invalid utf-8 characters are replaced.
-TEST_F(JSONParserTest, ReplaceInvalidCharacters) {
- const std::string bogus_char = "";
- const std::string quoted_bogus_char = "\"" + bogus_char + "\"";
- std::unique_ptr<JSONParser> parser(
- NewTestParser(quoted_bogus_char, JSON_REPLACE_INVALID_CHARACTERS));
- Optional<Value> value(parser->ConsumeString());
- ASSERT_TRUE(value);
- std::string str;
- EXPECT_TRUE(value->GetAsString(&str));
- EXPECT_EQ(kUnicodeReplacementString, str);
-}
-
-TEST_F(JSONParserTest, ReplaceInvalidUTF16EscapeSequence) {
- const std::string invalid = "\"\\ufffe\"";
- std::unique_ptr<JSONParser> parser(
- NewTestParser(invalid, JSON_REPLACE_INVALID_CHARACTERS));
- Optional<Value> value(parser->ConsumeString());
- ASSERT_TRUE(value);
- std::string str;
- EXPECT_TRUE(value->GetAsString(&str));
- EXPECT_EQ(kUnicodeReplacementString, str);
-}
-
-TEST_F(JSONParserTest, ParseNumberErrors) {
- const struct {
- const char* input;
- bool parse_success;
- double value;
- } kCases[] = {
- // clang-format off
- {"1", true, 1},
- {"2.", false, 0},
- {"42", true, 42},
- {"6e", false, 0},
- {"43e2", true, 4300},
- {"43e-", false, 0},
- {"9e-3", true, 0.009},
- {"2e+", false, 0},
- {"2e+2", true, 200},
- // clang-format on
- };
-
- for (unsigned int i = 0; i < arraysize(kCases); ++i) {
- auto test_case = kCases[i];
- SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case.input));
-
- std::unique_ptr<char[]> input_owner;
- StringPiece input =
- MakeNotNullTerminatedInput(test_case.input, &input_owner);
-
- std::unique_ptr<Value> result = JSONReader::Read(input);
- if (test_case.parse_success) {
- EXPECT_TRUE(result);
- } else {
- EXPECT_FALSE(result);
- }
-
- if (!result)
- continue;
-
- double double_value = 0;
- EXPECT_TRUE(result->GetAsDouble(&double_value));
- EXPECT_EQ(test_case.value, double_value);
- }
-}
-
-TEST_F(JSONParserTest, UnterminatedInputs) {
- const char* kCases[] = {
- // clang-format off
- "/",
- "//",
- "/*",
- "\"xxxxxx",
- "\"",
- "{ ",
- "[\t",
- "tru",
- "fals",
- "nul",
- "\"\\x",
- "\"\\x2",
- "\"\\u123",
- "\"\\uD803\\u",
- "\"\\",
- "\"\\/",
- // clang-format on
- };
-
- for (unsigned int i = 0; i < arraysize(kCases); ++i) {
- auto* test_case = kCases[i];
- SCOPED_TRACE(StringPrintf("case %u: \"%s\"", i, test_case));
-
- std::unique_ptr<char[]> input_owner;
- StringPiece input = MakeNotNullTerminatedInput(test_case, &input_owner);
-
- EXPECT_FALSE(JSONReader::Read(input));
- }
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/json/json_reader_unittest.cc b/base/json/json_reader_unittest.cc
deleted file mode 100644
index 828fba0..0000000
--- a/base/json/json_reader_unittest.cc
+++ /dev/null
@@ -1,665 +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/json/json_reader.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#include "base/base_paths.h"
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/path_service.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(JSONReaderTest, Whitespace) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue(" null ");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_none());
-}
-
-TEST(JSONReaderTest, InvalidString) {
- EXPECT_FALSE(JSONReader().ReadToValue("nu"));
-}
-
-TEST(JSONReaderTest, SimpleBool) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("true ");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_bool());
-}
-
-TEST(JSONReaderTest, EmbeddedComments) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("/* comment */null");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_none());
- root = JSONReader().ReadToValue("40 /* comment */");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_int());
- root = JSONReader().ReadToValue("true // comment");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_bool());
- root = JSONReader().ReadToValue("/* comment */\"sample string\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string value;
- EXPECT_TRUE(root->GetAsString(&value));
- EXPECT_EQ("sample string", value);
- std::unique_ptr<ListValue> list =
- ListValue::From(JSONReader().ReadToValue("[1, /* comment, 2 ] */ \n 3]"));
- ASSERT_TRUE(list);
- EXPECT_EQ(2u, list->GetSize());
- int int_val = 0;
- EXPECT_TRUE(list->GetInteger(0, &int_val));
- EXPECT_EQ(1, int_val);
- EXPECT_TRUE(list->GetInteger(1, &int_val));
- EXPECT_EQ(3, int_val);
- list = ListValue::From(JSONReader().ReadToValue("[1, /*a*/2, 3]"));
- ASSERT_TRUE(list);
- EXPECT_EQ(3u, list->GetSize());
- root = JSONReader().ReadToValue("/* comment **/42");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_int());
- EXPECT_TRUE(root->GetAsInteger(&int_val));
- EXPECT_EQ(42, int_val);
- root = JSONReader().ReadToValue(
- "/* comment **/\n"
- "// */ 43\n"
- "44");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_int());
- EXPECT_TRUE(root->GetAsInteger(&int_val));
- EXPECT_EQ(44, int_val);
-}
-
-TEST(JSONReaderTest, Ints) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("43");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_int());
- int int_val = 0;
- EXPECT_TRUE(root->GetAsInteger(&int_val));
- EXPECT_EQ(43, int_val);
-}
-
-TEST(JSONReaderTest, NonDecimalNumbers) {
- // According to RFC4627, oct, hex, and leading zeros are invalid JSON.
- EXPECT_FALSE(JSONReader().ReadToValue("043"));
- EXPECT_FALSE(JSONReader().ReadToValue("0x43"));
- EXPECT_FALSE(JSONReader().ReadToValue("00"));
-}
-
-TEST(JSONReaderTest, NumberZero) {
- // Test 0 (which needs to be special cased because of the leading zero
- // clause).
- std::unique_ptr<Value> root = JSONReader().ReadToValue("0");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_int());
- int int_val = 1;
- EXPECT_TRUE(root->GetAsInteger(&int_val));
- EXPECT_EQ(0, int_val);
-}
-
-TEST(JSONReaderTest, LargeIntPromotion) {
- // Numbers that overflow ints should succeed, being internally promoted to
- // storage as doubles
- std::unique_ptr<Value> root = JSONReader().ReadToValue("2147483648");
- ASSERT_TRUE(root);
- double double_val;
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(2147483648.0, double_val);
- root = JSONReader().ReadToValue("-2147483649");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(-2147483649.0, double_val);
-}
-
-TEST(JSONReaderTest, Doubles) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("43.1");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(43.1, double_val);
-
- root = JSONReader().ReadToValue("4.3e-1");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(.43, double_val);
-
- root = JSONReader().ReadToValue("2.1e0");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(2.1, double_val);
-
- root = JSONReader().ReadToValue("2.1e+0001");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(21.0, double_val);
-
- root = JSONReader().ReadToValue("0.01");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(0.01, double_val);
-
- root = JSONReader().ReadToValue("1.00");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_double());
- double_val = 0.0;
- EXPECT_TRUE(root->GetAsDouble(&double_val));
- EXPECT_DOUBLE_EQ(1.0, double_val);
-}
-
-TEST(JSONReaderTest, FractionalNumbers) {
- // Fractional parts must have a digit before and after the decimal point.
- EXPECT_FALSE(JSONReader().ReadToValue("1."));
- EXPECT_FALSE(JSONReader().ReadToValue(".1"));
- EXPECT_FALSE(JSONReader().ReadToValue("1.e10"));
-}
-
-TEST(JSONReaderTest, ExponentialNumbers) {
- // Exponent must have a digit following the 'e'.
- EXPECT_FALSE(JSONReader().ReadToValue("1e"));
- EXPECT_FALSE(JSONReader().ReadToValue("1E"));
- EXPECT_FALSE(JSONReader().ReadToValue("1e1."));
- EXPECT_FALSE(JSONReader().ReadToValue("1e1.0"));
-}
-
-TEST(JSONReaderTest, InvalidNAN) {
- EXPECT_FALSE(JSONReader().ReadToValue("1e1000"));
- EXPECT_FALSE(JSONReader().ReadToValue("-1e1000"));
- EXPECT_FALSE(JSONReader().ReadToValue("NaN"));
- EXPECT_FALSE(JSONReader().ReadToValue("nan"));
- EXPECT_FALSE(JSONReader().ReadToValue("inf"));
-}
-
-TEST(JSONReaderTest, InvalidNumbers) {
- EXPECT_FALSE(JSONReader().ReadToValue("4.3.1"));
- EXPECT_FALSE(JSONReader().ReadToValue("4e3.1"));
- EXPECT_FALSE(JSONReader().ReadToValue("4.a"));
-}
-
-TEST(JSONReader, SimpleString) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("\"hello world\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ("hello world", str_val);
-}
-
-TEST(JSONReaderTest, EmptyString) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("\"\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ("", str_val);
-}
-
-TEST(JSONReaderTest, BasicStringEscapes) {
- std::unique_ptr<Value> root =
- JSONReader().ReadToValue("\" \\\"\\\\\\/\\b\\f\\n\\r\\t\\v\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ(" \"\\/\b\f\n\r\t\v", str_val);
-}
-
-TEST(JSONReaderTest, UnicodeEscapes) {
- // Test hex and unicode escapes including the null character.
- std::unique_ptr<Value> root =
- JSONReader().ReadToValue("\"\\x41\\x00\\u1234\\u0000\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ(std::wstring(L"A\0\x1234\0", 4), UTF8ToWide(str_val));
-}
-
-TEST(JSONReaderTest, InvalidStrings) {
- EXPECT_FALSE(JSONReader().ReadToValue("\"no closing quote"));
- EXPECT_FALSE(JSONReader().ReadToValue("\"\\z invalid escape char\""));
- EXPECT_FALSE(JSONReader().ReadToValue("\"\\xAQ invalid hex code\""));
- EXPECT_FALSE(JSONReader().ReadToValue("not enough hex chars\\x1\""));
- EXPECT_FALSE(JSONReader().ReadToValue("\"not enough escape chars\\u123\""));
- EXPECT_FALSE(
- JSONReader().ReadToValue("\"extra backslash at end of input\\\""));
-}
-
-TEST(JSONReaderTest, BasicArray) {
- std::unique_ptr<ListValue> list =
- ListValue::From(JSONReader::Read("[true, false, null]"));
- ASSERT_TRUE(list);
- EXPECT_EQ(3U, list->GetSize());
-
- // Test with trailing comma. Should be parsed the same as above.
- std::unique_ptr<Value> root2 =
- JSONReader::Read("[true, false, null, ]", JSON_ALLOW_TRAILING_COMMAS);
- EXPECT_TRUE(list->Equals(root2.get()));
-}
-
-TEST(JSONReaderTest, EmptyArray) {
- std::unique_ptr<ListValue> list = ListValue::From(JSONReader::Read("[]"));
- ASSERT_TRUE(list);
- EXPECT_EQ(0U, list->GetSize());
-}
-
-TEST(JSONReaderTest, NestedArrays) {
- std::unique_ptr<ListValue> list = ListValue::From(
- JSONReader::Read("[[true], [], [false, [], [null]], null]"));
- ASSERT_TRUE(list);
- EXPECT_EQ(4U, list->GetSize());
-
- // Lots of trailing commas.
- std::unique_ptr<Value> root2 =
- JSONReader::Read("[[true], [], [false, [], [null, ] , ], null,]",
- JSON_ALLOW_TRAILING_COMMAS);
- EXPECT_TRUE(list->Equals(root2.get()));
-}
-
-TEST(JSONReaderTest, InvalidArrays) {
- // Missing close brace.
- EXPECT_FALSE(JSONReader::Read("[[true], [], [false, [], [null]], null"));
-
- // Too many commas.
- EXPECT_FALSE(JSONReader::Read("[true,, null]"));
- EXPECT_FALSE(JSONReader::Read("[true,, null]", JSON_ALLOW_TRAILING_COMMAS));
-
- // No commas.
- EXPECT_FALSE(JSONReader::Read("[true null]"));
-
- // Trailing comma.
- EXPECT_FALSE(JSONReader::Read("[true,]"));
-}
-
-TEST(JSONReaderTest, ArrayTrailingComma) {
- // Valid if we set |allow_trailing_comma| to true.
- std::unique_ptr<ListValue> list =
- ListValue::From(JSONReader::Read("[true,]", JSON_ALLOW_TRAILING_COMMAS));
- ASSERT_TRUE(list);
- EXPECT_EQ(1U, list->GetSize());
- Value* tmp_value = nullptr;
- ASSERT_TRUE(list->Get(0, &tmp_value));
- EXPECT_TRUE(tmp_value->is_bool());
- bool bool_value = false;
- EXPECT_TRUE(tmp_value->GetAsBoolean(&bool_value));
- EXPECT_TRUE(bool_value);
-}
-
-TEST(JSONReaderTest, ArrayTrailingCommaNoEmptyElements) {
- // Don't allow empty elements, even if |allow_trailing_comma| is
- // true.
- EXPECT_FALSE(JSONReader::Read("[,]", JSON_ALLOW_TRAILING_COMMAS));
- EXPECT_FALSE(JSONReader::Read("[true,,]", JSON_ALLOW_TRAILING_COMMAS));
- EXPECT_FALSE(JSONReader::Read("[,true,]", JSON_ALLOW_TRAILING_COMMAS));
- EXPECT_FALSE(JSONReader::Read("[true,,false]", JSON_ALLOW_TRAILING_COMMAS));
-}
-
-TEST(JSONReaderTest, EmptyDictionary) {
- std::unique_ptr<DictionaryValue> dict_val =
- DictionaryValue::From(JSONReader::Read("{}"));
- ASSERT_TRUE(dict_val);
-}
-
-TEST(JSONReaderTest, CompleteDictionary) {
- auto dict_val = DictionaryValue::From(JSONReader::Read(
- "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\" }"));
- ASSERT_TRUE(dict_val);
- double double_val = 0.0;
- EXPECT_TRUE(dict_val->GetDouble("number", &double_val));
- EXPECT_DOUBLE_EQ(9.87654321, double_val);
- Value* null_val = nullptr;
- ASSERT_TRUE(dict_val->Get("null", &null_val));
- EXPECT_TRUE(null_val->is_none());
- std::string str_val;
- EXPECT_TRUE(dict_val->GetString("S", &str_val));
- EXPECT_EQ("str", str_val);
-
- std::unique_ptr<Value> root2 = JSONReader::Read(
- "{\"number\":9.87654321, \"null\":null , \"\\x53\" : \"str\", }",
- JSON_ALLOW_TRAILING_COMMAS);
- ASSERT_TRUE(root2);
- EXPECT_TRUE(dict_val->Equals(root2.get()));
-
- // Test newline equivalence.
- root2 = JSONReader::Read(
- "{\n"
- " \"number\":9.87654321,\n"
- " \"null\":null,\n"
- " \"\\x53\":\"str\",\n"
- "}\n",
- JSON_ALLOW_TRAILING_COMMAS);
- ASSERT_TRUE(root2);
- EXPECT_TRUE(dict_val->Equals(root2.get()));
-
- root2 = JSONReader::Read(
- "{\r\n"
- " \"number\":9.87654321,\r\n"
- " \"null\":null,\r\n"
- " \"\\x53\":\"str\",\r\n"
- "}\r\n",
- JSON_ALLOW_TRAILING_COMMAS);
- ASSERT_TRUE(root2);
- EXPECT_TRUE(dict_val->Equals(root2.get()));
-}
-
-TEST(JSONReaderTest, NestedDictionaries) {
- std::unique_ptr<DictionaryValue> dict_val =
- DictionaryValue::From(JSONReader::Read(
- "{\"inner\":{\"array\":[true]},\"false\":false,\"d\":{}}"));
- ASSERT_TRUE(dict_val);
- DictionaryValue* inner_dict = nullptr;
- ASSERT_TRUE(dict_val->GetDictionary("inner", &inner_dict));
- ListValue* inner_array = nullptr;
- ASSERT_TRUE(inner_dict->GetList("array", &inner_array));
- EXPECT_EQ(1U, inner_array->GetSize());
- bool bool_value = true;
- EXPECT_TRUE(dict_val->GetBoolean("false", &bool_value));
- EXPECT_FALSE(bool_value);
- inner_dict = nullptr;
- EXPECT_TRUE(dict_val->GetDictionary("d", &inner_dict));
-
- std::unique_ptr<Value> root2 = JSONReader::Read(
- "{\"inner\": {\"array\":[true] , },\"false\":false,\"d\":{},}",
- JSON_ALLOW_TRAILING_COMMAS);
- EXPECT_TRUE(dict_val->Equals(root2.get()));
-}
-
-TEST(JSONReaderTest, DictionaryKeysWithPeriods) {
- std::unique_ptr<DictionaryValue> dict_val = DictionaryValue::From(
- JSONReader::Read("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}"));
- ASSERT_TRUE(dict_val);
- int integer_value = 0;
- EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion("a.b", &integer_value));
- EXPECT_EQ(3, integer_value);
- EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion("c", &integer_value));
- EXPECT_EQ(2, integer_value);
- DictionaryValue* inner_dict = nullptr;
- ASSERT_TRUE(
- dict_val->GetDictionaryWithoutPathExpansion("d.e.f", &inner_dict));
- EXPECT_EQ(1U, inner_dict->size());
- EXPECT_TRUE(
- inner_dict->GetIntegerWithoutPathExpansion("g.h.i.j", &integer_value));
- EXPECT_EQ(1, integer_value);
-
- dict_val =
- DictionaryValue::From(JSONReader::Read("{\"a\":{\"b\":2},\"a.b\":1}"));
- ASSERT_TRUE(dict_val);
- EXPECT_TRUE(dict_val->GetInteger("a.b", &integer_value));
- EXPECT_EQ(2, integer_value);
- EXPECT_TRUE(dict_val->GetIntegerWithoutPathExpansion("a.b", &integer_value));
- EXPECT_EQ(1, integer_value);
-}
-
-TEST(JSONReaderTest, InvalidDictionaries) {
- // No closing brace.
- EXPECT_FALSE(JSONReader::Read("{\"a\": true"));
-
- // Keys must be quoted strings.
- EXPECT_FALSE(JSONReader::Read("{foo:true}"));
- EXPECT_FALSE(JSONReader::Read("{1234: false}"));
- EXPECT_FALSE(JSONReader::Read("{:false}"));
-
- // Trailing comma.
- EXPECT_FALSE(JSONReader::Read("{\"a\":true,}"));
-
- // Too many commas.
- EXPECT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}"));
- EXPECT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}",
- JSON_ALLOW_TRAILING_COMMAS));
-
- // No separator.
- EXPECT_FALSE(JSONReader::Read("{\"a\" \"b\"}"));
-
- // Lone comma.
- EXPECT_FALSE(JSONReader::Read("{,}"));
- EXPECT_FALSE(JSONReader::Read("{,}", JSON_ALLOW_TRAILING_COMMAS));
- EXPECT_FALSE(JSONReader::Read("{\"a\":true,,}", JSON_ALLOW_TRAILING_COMMAS));
- EXPECT_FALSE(JSONReader::Read("{,\"a\":true}", JSON_ALLOW_TRAILING_COMMAS));
- EXPECT_FALSE(JSONReader::Read("{\"a\":true,,\"b\":false}",
- JSON_ALLOW_TRAILING_COMMAS));
-}
-
-TEST(JSONReaderTest, StackOverflow) {
- std::string evil(1000000, '[');
- evil.append(std::string(1000000, ']'));
- EXPECT_FALSE(JSONReader::Read(evil));
-
- // A few thousand adjacent lists is fine.
- std::string not_evil("[");
- not_evil.reserve(15010);
- for (int i = 0; i < 5000; ++i)
- not_evil.append("[],");
- not_evil.append("[]]");
- std::unique_ptr<ListValue> list = ListValue::From(JSONReader::Read(not_evil));
- ASSERT_TRUE(list);
- EXPECT_EQ(5001U, list->GetSize());
-}
-
-TEST(JSONReaderTest, UTF8Input) {
- std::unique_ptr<Value> root =
- JSONReader().ReadToValue("\"\xe7\xbd\x91\xe9\xa1\xb5\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ(L"\x7f51\x9875", UTF8ToWide(str_val));
-
- std::unique_ptr<DictionaryValue> dict_val =
- DictionaryValue::From(JSONReader().ReadToValue(
- "{\"path\": \"/tmp/\xc3\xa0\xc3\xa8\xc3\xb2.png\"}"));
- ASSERT_TRUE(dict_val);
- EXPECT_TRUE(dict_val->GetString("path", &str_val));
- EXPECT_EQ("/tmp/\xC3\xA0\xC3\xA8\xC3\xB2.png", str_val);
-}
-
-TEST(JSONReaderTest, InvalidUTF8Input) {
- EXPECT_FALSE(JSONReader().ReadToValue("\"345\xb0\xa1\xb0\xa2\""));
- EXPECT_FALSE(JSONReader().ReadToValue("\"123\xc0\x81\""));
- EXPECT_FALSE(JSONReader().ReadToValue("\"abc\xc0\xae\""));
-}
-
-TEST(JSONReaderTest, UTF16Escapes) {
- std::unique_ptr<Value> root = JSONReader().ReadToValue("\"\\u20ac3,14\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ(
- "\xe2\x82\xac"
- "3,14",
- str_val);
-
- root = JSONReader().ReadToValue("\"\\ud83d\\udca9\\ud83d\\udc6c\"");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_string());
- str_val.clear();
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ("\xf0\x9f\x92\xa9\xf0\x9f\x91\xac", str_val);
-}
-
-TEST(JSONReaderTest, InvalidUTF16Escapes) {
- const char* const cases[] = {
- "\"\\u123\"", // Invalid scalar.
- "\"\\ud83d\"", // Invalid scalar.
- "\"\\u$%@!\"", // Invalid scalar.
- "\"\\uzz89\"", // Invalid scalar.
- "\"\\ud83d\\udca\"", // Invalid lower surrogate.
- "\"\\ud83d\\ud83d\"", // Invalid lower surrogate.
- "\"\\ud83d\\uaaaZ\"" // Invalid lower surrogate.
- "\"\\ud83foo\"", // No lower surrogate.
- "\"\\ud83d\\foo\"" // No lower surrogate.
- "\"\\ud83\\foo\"" // Invalid upper surrogate.
- "\"\\ud83d\\u1\"" // No lower surrogate.
- "\"\\ud83\\u1\"" // Invalid upper surrogate.
- };
- std::unique_ptr<Value> root;
- for (size_t i = 0; i < arraysize(cases); ++i) {
- root = JSONReader().ReadToValue(cases[i]);
- EXPECT_FALSE(root) << cases[i];
- }
-}
-
-TEST(JSONReaderTest, LiteralRoots) {
- std::unique_ptr<Value> root = JSONReader::Read("null");
- ASSERT_TRUE(root);
- EXPECT_TRUE(root->is_none());
-
- root = JSONReader::Read("true");
- ASSERT_TRUE(root);
- bool bool_value;
- EXPECT_TRUE(root->GetAsBoolean(&bool_value));
- EXPECT_TRUE(bool_value);
-
- root = JSONReader::Read("10");
- ASSERT_TRUE(root);
- int integer_value;
- EXPECT_TRUE(root->GetAsInteger(&integer_value));
- EXPECT_EQ(10, integer_value);
-
- root = JSONReader::Read("\"root\"");
- ASSERT_TRUE(root);
- std::string str_val;
- EXPECT_TRUE(root->GetAsString(&str_val));
- EXPECT_EQ("root", str_val);
-}
-
-TEST(JSONReaderTest, ReadFromFile) {
- FilePath path;
- ASSERT_TRUE(PathService::Get(base::DIR_TEST_DATA, &path));
- path = path.AppendASCII("json");
- ASSERT_TRUE(base::PathExists(path));
-
- std::string input;
- ASSERT_TRUE(ReadFileToString(path.AppendASCII("bom_feff.json"), &input));
-
- JSONReader reader;
- std::unique_ptr<Value> root(reader.ReadToValue(input));
- ASSERT_TRUE(root) << reader.GetErrorMessage();
- EXPECT_TRUE(root->is_dict());
-}
-
-// Tests that the root of a JSON object can be deleted safely while its
-// children outlive it.
-TEST(JSONReaderTest, StringOptimizations) {
- std::unique_ptr<Value> dict_literal_0;
- std::unique_ptr<Value> dict_literal_1;
- std::unique_ptr<Value> dict_string_0;
- std::unique_ptr<Value> dict_string_1;
- std::unique_ptr<Value> list_value_0;
- std::unique_ptr<Value> list_value_1;
-
- {
- std::unique_ptr<Value> root = JSONReader::Read(
- "{"
- " \"test\": {"
- " \"foo\": true,"
- " \"bar\": 3.14,"
- " \"baz\": \"bat\","
- " \"moo\": \"cow\""
- " },"
- " \"list\": ["
- " \"a\","
- " \"b\""
- " ]"
- "}",
- JSON_PARSE_RFC);
- ASSERT_TRUE(root);
-
- DictionaryValue* root_dict = nullptr;
- ASSERT_TRUE(root->GetAsDictionary(&root_dict));
-
- DictionaryValue* dict = nullptr;
- ListValue* list = nullptr;
-
- ASSERT_TRUE(root_dict->GetDictionary("test", &dict));
- ASSERT_TRUE(root_dict->GetList("list", &list));
-
- ASSERT_TRUE(dict->Remove("foo", &dict_literal_0));
- ASSERT_TRUE(dict->Remove("bar", &dict_literal_1));
- ASSERT_TRUE(dict->Remove("baz", &dict_string_0));
- ASSERT_TRUE(dict->Remove("moo", &dict_string_1));
-
- ASSERT_EQ(2u, list->GetSize());
- ASSERT_TRUE(list->Remove(0, &list_value_0));
- ASSERT_TRUE(list->Remove(0, &list_value_1));
- }
-
- bool b = false;
- double d = 0;
- std::string s;
-
- EXPECT_TRUE(dict_literal_0->GetAsBoolean(&b));
- EXPECT_TRUE(b);
-
- EXPECT_TRUE(dict_literal_1->GetAsDouble(&d));
- EXPECT_EQ(3.14, d);
-
- EXPECT_TRUE(dict_string_0->GetAsString(&s));
- EXPECT_EQ("bat", s);
-
- EXPECT_TRUE(dict_string_1->GetAsString(&s));
- EXPECT_EQ("cow", s);
-
- EXPECT_TRUE(list_value_0->GetAsString(&s));
- EXPECT_EQ("a", s);
- EXPECT_TRUE(list_value_1->GetAsString(&s));
- EXPECT_EQ("b", s);
-}
-
-// A smattering of invalid JSON designed to test specific portions of the
-// parser implementation against buffer overflow. Best run with DCHECKs so
-// that the one in NextChar fires.
-TEST(JSONReaderTest, InvalidSanity) {
- const char* const kInvalidJson[] = {
- "/* test *", "{\"foo\"", "{\"foo\":", " [", "\"\\u123g\"", "{\n\"eh:\n}",
- };
-
- for (size_t i = 0; i < arraysize(kInvalidJson); ++i) {
- JSONReader reader;
- LOG(INFO) << "Sanity test " << i << ": <" << kInvalidJson[i] << ">";
- EXPECT_FALSE(reader.ReadToValue(kInvalidJson[i]));
- EXPECT_NE(JSONReader::JSON_NO_ERROR, reader.error_code());
- EXPECT_NE("", reader.GetErrorMessage());
- }
-}
-
-TEST(JSONReaderTest, IllegalTrailingNull) {
- const char json[] = { '"', 'n', 'u', 'l', 'l', '"', '\0' };
- std::string json_string(json, sizeof(json));
- JSONReader reader;
- EXPECT_FALSE(reader.ReadToValue(json_string));
- EXPECT_EQ(JSONReader::JSON_UNEXPECTED_DATA_AFTER_ROOT, reader.error_code());
-}
-
-TEST(JSONReaderTest, MaxNesting) {
- std::string json(R"({"outer": { "inner": {"foo": true}}})");
- std::unique_ptr<Value> root;
- root = JSONReader::Read(json, JSON_PARSE_RFC, 3);
- ASSERT_FALSE(root);
- root = JSONReader::Read(json, JSON_PARSE_RFC, 4);
- ASSERT_TRUE(root);
-}
-
-} // namespace base
diff --git a/base/json/json_value_converter_unittest.cc b/base/json/json_value_converter_unittest.cc
deleted file mode 100644
index 322f5f0..0000000
--- a/base/json/json_value_converter_unittest.cc
+++ /dev/null
@@ -1,255 +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/json/json_value_converter.h"
-
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/json/json_reader.h"
-#include "base/strings/string_piece.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-// Very simple messages.
-struct SimpleMessage {
- enum SimpleEnum {
- FOO, BAR,
- };
- int foo;
- std::string bar;
- bool baz;
- bool bstruct;
- SimpleEnum simple_enum;
- std::vector<std::unique_ptr<int>> ints;
- std::vector<std::unique_ptr<std::string>> string_values;
- SimpleMessage() : foo(0), baz(false), bstruct(false), simple_enum(FOO) {}
-
- static bool ParseSimpleEnum(StringPiece value, SimpleEnum* field) {
- if (value == "foo") {
- *field = FOO;
- return true;
- } else if (value == "bar") {
- *field = BAR;
- return true;
- }
- return false;
- }
-
- static bool HasFieldPresent(const base::Value* value, bool* result) {
- *result = value != nullptr;
- return true;
- }
-
- static bool GetValueString(const base::Value* value, std::string* result) {
- const base::DictionaryValue* dict = nullptr;
- if (!value->GetAsDictionary(&dict))
- return false;
-
- if (!dict->GetString("val", result))
- return false;
-
- return true;
- }
-
- static void RegisterJSONConverter(
- base::JSONValueConverter<SimpleMessage>* converter) {
- converter->RegisterIntField("foo", &SimpleMessage::foo);
- converter->RegisterStringField("bar", &SimpleMessage::bar);
- converter->RegisterBoolField("baz", &SimpleMessage::baz);
- converter->RegisterCustomField<SimpleEnum>(
- "simple_enum", &SimpleMessage::simple_enum, &ParseSimpleEnum);
- converter->RegisterRepeatedInt("ints", &SimpleMessage::ints);
- converter->RegisterCustomValueField<bool>("bstruct",
- &SimpleMessage::bstruct,
- &HasFieldPresent);
- converter->RegisterRepeatedCustomValue<std::string>(
- "string_values",
- &SimpleMessage::string_values,
- &GetValueString);
- }
-};
-
-// For nested messages.
-struct NestedMessage {
- double foo;
- SimpleMessage child;
- std::vector<std::unique_ptr<SimpleMessage>> children;
-
- NestedMessage() : foo(0) {}
-
- static void RegisterJSONConverter(
- base::JSONValueConverter<NestedMessage>* converter) {
- converter->RegisterDoubleField("foo", &NestedMessage::foo);
- converter->RegisterNestedField("child", &NestedMessage::child);
- converter->RegisterRepeatedMessage("children", &NestedMessage::children);
- }
-};
-
-} // namespace
-
-TEST(JSONValueConverterTest, ParseSimpleMessage) {
- const char normal_data[] =
- "{\n"
- " \"foo\": 1,\n"
- " \"bar\": \"bar\",\n"
- " \"baz\": true,\n"
- " \"bstruct\": {},\n"
- " \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
- " \"simple_enum\": \"foo\","
- " \"ints\": [1, 2]"
- "}\n";
-
- std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
- SimpleMessage message;
- base::JSONValueConverter<SimpleMessage> converter;
- EXPECT_TRUE(converter.Convert(*value.get(), &message));
-
- EXPECT_EQ(1, message.foo);
- EXPECT_EQ("bar", message.bar);
- EXPECT_TRUE(message.baz);
- EXPECT_EQ(SimpleMessage::FOO, message.simple_enum);
- EXPECT_EQ(2, static_cast<int>(message.ints.size()));
- ASSERT_EQ(2U, message.string_values.size());
- EXPECT_EQ("value_1", *message.string_values[0]);
- EXPECT_EQ("value_2", *message.string_values[1]);
- EXPECT_EQ(1, *(message.ints[0]));
- EXPECT_EQ(2, *(message.ints[1]));
-}
-
-TEST(JSONValueConverterTest, ParseNestedMessage) {
- const char normal_data[] =
- "{\n"
- " \"foo\": 1.0,\n"
- " \"child\": {\n"
- " \"foo\": 1,\n"
- " \"bar\": \"bar\",\n"
- " \"bstruct\": {},\n"
- " \"string_values\": [{\"val\": \"value_1\"}, {\"val\": \"value_2\"}],"
- " \"baz\": true\n"
- " },\n"
- " \"children\": [{\n"
- " \"foo\": 2,\n"
- " \"bar\": \"foobar\",\n"
- " \"bstruct\": \"\",\n"
- " \"string_values\": [{\"val\": \"value_1\"}],"
- " \"baz\": true\n"
- " },\n"
- " {\n"
- " \"foo\": 3,\n"
- " \"bar\": \"barbaz\",\n"
- " \"baz\": false\n"
- " }]\n"
- "}\n";
-
- std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
- NestedMessage message;
- base::JSONValueConverter<NestedMessage> converter;
- EXPECT_TRUE(converter.Convert(*value.get(), &message));
-
- EXPECT_EQ(1.0, message.foo);
- EXPECT_EQ(1, message.child.foo);
- EXPECT_EQ("bar", message.child.bar);
- EXPECT_TRUE(message.child.baz);
- EXPECT_TRUE(message.child.bstruct);
- ASSERT_EQ(2U, message.child.string_values.size());
- EXPECT_EQ("value_1", *message.child.string_values[0]);
- EXPECT_EQ("value_2", *message.child.string_values[1]);
-
- EXPECT_EQ(2, static_cast<int>(message.children.size()));
- const SimpleMessage* first_child = message.children[0].get();
- ASSERT_TRUE(first_child);
- EXPECT_EQ(2, first_child->foo);
- EXPECT_EQ("foobar", first_child->bar);
- EXPECT_TRUE(first_child->baz);
- EXPECT_TRUE(first_child->bstruct);
- ASSERT_EQ(1U, first_child->string_values.size());
- EXPECT_EQ("value_1", *first_child->string_values[0]);
-
- const SimpleMessage* second_child = message.children[1].get();
- ASSERT_TRUE(second_child);
- EXPECT_EQ(3, second_child->foo);
- EXPECT_EQ("barbaz", second_child->bar);
- EXPECT_FALSE(second_child->baz);
- EXPECT_FALSE(second_child->bstruct);
- EXPECT_EQ(0U, second_child->string_values.size());
-}
-
-TEST(JSONValueConverterTest, ParseFailures) {
- const char normal_data[] =
- "{\n"
- " \"foo\": 1,\n"
- " \"bar\": 2,\n" // "bar" is an integer here.
- " \"baz\": true,\n"
- " \"ints\": [1, 2]"
- "}\n";
-
- std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
- SimpleMessage message;
- base::JSONValueConverter<SimpleMessage> converter;
- EXPECT_FALSE(converter.Convert(*value.get(), &message));
- // Do not check the values below. |message| may be modified during
- // Convert() even it fails.
-}
-
-TEST(JSONValueConverterTest, ParseWithMissingFields) {
- const char normal_data[] =
- "{\n"
- " \"foo\": 1,\n"
- " \"baz\": true,\n"
- " \"ints\": [1, 2]"
- "}\n";
-
- std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
- SimpleMessage message;
- base::JSONValueConverter<SimpleMessage> converter;
- // Convert() still succeeds even if the input doesn't have "bar" field.
- EXPECT_TRUE(converter.Convert(*value.get(), &message));
-
- EXPECT_EQ(1, message.foo);
- EXPECT_TRUE(message.baz);
- EXPECT_EQ(2, static_cast<int>(message.ints.size()));
- EXPECT_EQ(1, *(message.ints[0]));
- EXPECT_EQ(2, *(message.ints[1]));
-}
-
-TEST(JSONValueConverterTest, EnumParserFails) {
- const char normal_data[] =
- "{\n"
- " \"foo\": 1,\n"
- " \"bar\": \"bar\",\n"
- " \"baz\": true,\n"
- " \"simple_enum\": \"baz\","
- " \"ints\": [1, 2]"
- "}\n";
-
- std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
- SimpleMessage message;
- base::JSONValueConverter<SimpleMessage> converter;
- EXPECT_FALSE(converter.Convert(*value.get(), &message));
- // No check the values as mentioned above.
-}
-
-TEST(JSONValueConverterTest, RepeatedValueErrorInTheMiddle) {
- const char normal_data[] =
- "{\n"
- " \"foo\": 1,\n"
- " \"bar\": \"bar\",\n"
- " \"baz\": true,\n"
- " \"simple_enum\": \"baz\","
- " \"ints\": [1, false]"
- "}\n";
-
- std::unique_ptr<Value> value = base::JSONReader::Read(normal_data);
- SimpleMessage message;
- base::JSONValueConverter<SimpleMessage> converter;
- EXPECT_FALSE(converter.Convert(*value.get(), &message));
- // No check the values as mentioned above.
-}
-
-} // namespace base
diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc
deleted file mode 100644
index b358dec..0000000
--- a/base/json/json_value_serializer_unittest.cc
+++ /dev/null
@@ -1,487 +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 <string>
-
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/json/json_file_value_serializer.h"
-#include "base/json/json_reader.h"
-#include "base/json/json_string_value_serializer.h"
-#include "base/json/json_writer.h"
-#include "base/path_service.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/values.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Some proper JSON to test with:
-const char kProperJSON[] =
- "{\n"
- " \"compound\": {\n"
- " \"a\": 1,\n"
- " \"b\": 2\n"
- " },\n"
- " \"some_String\": \"1337\",\n"
- " \"some_int\": 42,\n"
- " \"the_list\": [ \"val1\", \"val2\" ]\n"
- "}\n";
-
-// Some proper JSON with trailing commas:
-const char kProperJSONWithCommas[] =
- "{\n"
- "\t\"some_int\": 42,\n"
- "\t\"some_String\": \"1337\",\n"
- "\t\"the_list\": [\"val1\", \"val2\", ],\n"
- "\t\"compound\": { \"a\": 1, \"b\": 2, },\n"
- "}\n";
-
-// kProperJSON with a few misc characters at the begin and end.
-const char kProperJSONPadded[] =
- ")]}'\n"
- "{\n"
- " \"compound\": {\n"
- " \"a\": 1,\n"
- " \"b\": 2\n"
- " },\n"
- " \"some_String\": \"1337\",\n"
- " \"some_int\": 42,\n"
- " \"the_list\": [ \"val1\", \"val2\" ]\n"
- "}\n"
- "?!ab\n";
-
-const char kWinLineEnds[] = "\r\n";
-const char kLinuxLineEnds[] = "\n";
-
-// Verifies the generated JSON against the expected output.
-void CheckJSONIsStillTheSame(const Value& value) {
- // Serialize back the output.
- std::string serialized_json;
- JSONStringValueSerializer str_serializer(&serialized_json);
- str_serializer.set_pretty_print(true);
- ASSERT_TRUE(str_serializer.Serialize(value));
- // Unify line endings between platforms.
- ReplaceSubstringsAfterOffset(&serialized_json, 0,
- kWinLineEnds, kLinuxLineEnds);
- // Now compare the input with the output.
- ASSERT_EQ(kProperJSON, serialized_json);
-}
-
-void ValidateJsonList(const std::string& json) {
- std::unique_ptr<ListValue> list = ListValue::From(JSONReader::Read(json));
- ASSERT_TRUE(list);
- ASSERT_EQ(1U, list->GetSize());
- Value* elt = nullptr;
- ASSERT_TRUE(list->Get(0, &elt));
- int value = 0;
- ASSERT_TRUE(elt && elt->GetAsInteger(&value));
- ASSERT_EQ(1, value);
-}
-
-// Test proper JSON deserialization from string is working.
-TEST(JSONValueDeserializerTest, ReadProperJSONFromString) {
- // Try to deserialize it through the serializer.
- JSONStringValueDeserializer str_deserializer(kProperJSON);
-
- int error_code = 0;
- std::string error_message;
- std::unique_ptr<Value> value =
- str_deserializer.Deserialize(&error_code, &error_message);
- ASSERT_TRUE(value);
- ASSERT_EQ(0, error_code);
- ASSERT_TRUE(error_message.empty());
- // Verify if the same JSON is still there.
- CheckJSONIsStillTheSame(*value);
-}
-
-// Test proper JSON deserialization from a StringPiece substring.
-TEST(JSONValueDeserializerTest, ReadProperJSONFromStringPiece) {
- // Create a StringPiece for the substring of kProperJSONPadded that matches
- // kProperJSON.
- StringPiece proper_json(kProperJSONPadded);
- proper_json = proper_json.substr(5, proper_json.length() - 10);
- JSONStringValueDeserializer str_deserializer(proper_json);
-
- int error_code = 0;
- std::string error_message;
- std::unique_ptr<Value> value =
- str_deserializer.Deserialize(&error_code, &error_message);
- ASSERT_TRUE(value);
- ASSERT_EQ(0, error_code);
- ASSERT_TRUE(error_message.empty());
- // Verify if the same JSON is still there.
- CheckJSONIsStillTheSame(*value);
-}
-
-// Test that trialing commas are only properly deserialized from string when
-// the proper flag for that is set.
-TEST(JSONValueDeserializerTest, ReadJSONWithTrailingCommasFromString) {
- // Try to deserialize it through the serializer.
- JSONStringValueDeserializer str_deserializer(kProperJSONWithCommas);
-
- int error_code = 0;
- std::string error_message;
- std::unique_ptr<Value> value =
- str_deserializer.Deserialize(&error_code, &error_message);
- ASSERT_FALSE(value);
- ASSERT_NE(0, error_code);
- ASSERT_FALSE(error_message.empty());
- // Repeat with commas allowed.
- JSONStringValueDeserializer str_deserializer2(kProperJSONWithCommas,
- JSON_ALLOW_TRAILING_COMMAS);
- value = str_deserializer2.Deserialize(&error_code, &error_message);
- ASSERT_TRUE(value);
- ASSERT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code);
- // Verify if the same JSON is still there.
- CheckJSONIsStillTheSame(*value);
-}
-
-// Test proper JSON deserialization from file is working.
-TEST(JSONValueDeserializerTest, ReadProperJSONFromFile) {
- ScopedTempDir tempdir;
- ASSERT_TRUE(tempdir.CreateUniqueTempDir());
- // Write it down in the file.
- FilePath temp_file(tempdir.GetPath().AppendASCII("test.json"));
- ASSERT_EQ(static_cast<int>(strlen(kProperJSON)),
- WriteFile(temp_file, kProperJSON, strlen(kProperJSON)));
-
- // Try to deserialize it through the serializer.
- JSONFileValueDeserializer file_deserializer(temp_file);
-
- int error_code = 0;
- std::string error_message;
- std::unique_ptr<Value> value =
- file_deserializer.Deserialize(&error_code, &error_message);
- ASSERT_TRUE(value);
- ASSERT_EQ(0, error_code);
- ASSERT_TRUE(error_message.empty());
- // Verify if the same JSON is still there.
- CheckJSONIsStillTheSame(*value);
-}
-
-// Test that trialing commas are only properly deserialized from file when
-// the proper flag for that is set.
-TEST(JSONValueDeserializerTest, ReadJSONWithCommasFromFile) {
- ScopedTempDir tempdir;
- ASSERT_TRUE(tempdir.CreateUniqueTempDir());
- // Write it down in the file.
- FilePath temp_file(tempdir.GetPath().AppendASCII("test.json"));
- ASSERT_EQ(static_cast<int>(strlen(kProperJSONWithCommas)),
- WriteFile(temp_file, kProperJSONWithCommas,
- strlen(kProperJSONWithCommas)));
-
- // Try to deserialize it through the serializer.
- JSONFileValueDeserializer file_deserializer(temp_file);
- // This must fail without the proper flag.
- int error_code = 0;
- std::string error_message;
- std::unique_ptr<Value> value =
- file_deserializer.Deserialize(&error_code, &error_message);
- ASSERT_FALSE(value);
- ASSERT_NE(0, error_code);
- ASSERT_FALSE(error_message.empty());
- // Repeat with commas allowed.
- JSONFileValueDeserializer file_deserializer2(temp_file,
- JSON_ALLOW_TRAILING_COMMAS);
- value = file_deserializer2.Deserialize(&error_code, &error_message);
- ASSERT_TRUE(value);
- ASSERT_EQ(JSONReader::JSON_TRAILING_COMMA, error_code);
- // Verify if the same JSON is still there.
- CheckJSONIsStillTheSame(*value);
-}
-
-TEST(JSONValueDeserializerTest, AllowTrailingComma) {
- static const char kTestWithCommas[] = "{\"key\": [true,],}";
- static const char kTestNoCommas[] = "{\"key\": [true]}";
-
- JSONStringValueDeserializer deserializer(kTestWithCommas,
- JSON_ALLOW_TRAILING_COMMAS);
- JSONStringValueDeserializer deserializer_expected(kTestNoCommas);
- std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(root);
- std::unique_ptr<Value> root_expected;
- root_expected = deserializer_expected.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(root_expected);
- ASSERT_TRUE(root->Equals(root_expected.get()));
-}
-
-TEST(JSONValueSerializerTest, Roundtrip) {
- static const char kOriginalSerialization[] =
- "{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}";
- JSONStringValueDeserializer deserializer(kOriginalSerialization);
- std::unique_ptr<DictionaryValue> root_dict =
- DictionaryValue::From(deserializer.Deserialize(nullptr, nullptr));
- ASSERT_TRUE(root_dict);
-
- Value* null_value = nullptr;
- ASSERT_TRUE(root_dict->Get("null", &null_value));
- ASSERT_TRUE(null_value);
- ASSERT_TRUE(null_value->is_none());
-
- bool bool_value = false;
- ASSERT_TRUE(root_dict->GetBoolean("bool", &bool_value));
- ASSERT_TRUE(bool_value);
-
- int int_value = 0;
- ASSERT_TRUE(root_dict->GetInteger("int", &int_value));
- ASSERT_EQ(42, int_value);
-
- double double_value = 0.0;
- ASSERT_TRUE(root_dict->GetDouble("double", &double_value));
- ASSERT_DOUBLE_EQ(3.14, double_value);
-
- std::string test_serialization;
- JSONStringValueSerializer mutable_serializer(&test_serialization);
- ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
- ASSERT_EQ(kOriginalSerialization, test_serialization);
-
- mutable_serializer.set_pretty_print(true);
- ASSERT_TRUE(mutable_serializer.Serialize(*root_dict));
- // JSON output uses a different newline style on Windows than on other
- // platforms.
-#if defined(OS_WIN)
-#define JSON_NEWLINE "\r\n"
-#else
-#define JSON_NEWLINE "\n"
-#endif
- const std::string pretty_serialization =
- "{" JSON_NEWLINE
- " \"bool\": true," JSON_NEWLINE
- " \"double\": 3.14," JSON_NEWLINE
- " \"int\": 42," JSON_NEWLINE
- " \"list\": [ 1, 2 ]," JSON_NEWLINE
- " \"null\": null" JSON_NEWLINE
- "}" JSON_NEWLINE;
-#undef JSON_NEWLINE
- ASSERT_EQ(pretty_serialization, test_serialization);
-}
-
-TEST(JSONValueSerializerTest, StringEscape) {
- string16 all_chars;
- for (int i = 1; i < 256; ++i) {
- all_chars += static_cast<char16>(i);
- }
- // Generated in in Firefox using the following js (with an extra backslash for
- // double quote):
- // var s = '';
- // for (var i = 1; i < 256; ++i) { s += String.fromCharCode(i); }
- // uneval(s).replace(/\\/g, "\\\\");
- std::string all_chars_expected =
- "\\u0001\\u0002\\u0003\\u0004\\u0005\\u0006\\u0007\\b\\t\\n\\u000B\\f\\r"
- "\\u000E\\u000F\\u0010\\u0011\\u0012\\u0013\\u0014\\u0015\\u0016\\u0017"
- "\\u0018\\u0019\\u001A\\u001B\\u001C\\u001D\\u001E\\u001F !\\\"#$%&'()*+,"
- "-./0123456789:;\\u003C=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\\\]^_`abcde"
- "fghijklmnopqrstuvwxyz{|}~\x7F\xC2\x80\xC2\x81\xC2\x82\xC2\x83\xC2\x84"
- "\xC2\x85\xC2\x86\xC2\x87\xC2\x88\xC2\x89\xC2\x8A\xC2\x8B\xC2\x8C\xC2\x8D"
- "\xC2\x8E\xC2\x8F\xC2\x90\xC2\x91\xC2\x92\xC2\x93\xC2\x94\xC2\x95\xC2\x96"
- "\xC2\x97\xC2\x98\xC2\x99\xC2\x9A\xC2\x9B\xC2\x9C\xC2\x9D\xC2\x9E\xC2\x9F"
- "\xC2\xA0\xC2\xA1\xC2\xA2\xC2\xA3\xC2\xA4\xC2\xA5\xC2\xA6\xC2\xA7\xC2\xA8"
- "\xC2\xA9\xC2\xAA\xC2\xAB\xC2\xAC\xC2\xAD\xC2\xAE\xC2\xAF\xC2\xB0\xC2\xB1"
- "\xC2\xB2\xC2\xB3\xC2\xB4\xC2\xB5\xC2\xB6\xC2\xB7\xC2\xB8\xC2\xB9\xC2\xBA"
- "\xC2\xBB\xC2\xBC\xC2\xBD\xC2\xBE\xC2\xBF\xC3\x80\xC3\x81\xC3\x82\xC3\x83"
- "\xC3\x84\xC3\x85\xC3\x86\xC3\x87\xC3\x88\xC3\x89\xC3\x8A\xC3\x8B\xC3\x8C"
- "\xC3\x8D\xC3\x8E\xC3\x8F\xC3\x90\xC3\x91\xC3\x92\xC3\x93\xC3\x94\xC3\x95"
- "\xC3\x96\xC3\x97\xC3\x98\xC3\x99\xC3\x9A\xC3\x9B\xC3\x9C\xC3\x9D\xC3\x9E"
- "\xC3\x9F\xC3\xA0\xC3\xA1\xC3\xA2\xC3\xA3\xC3\xA4\xC3\xA5\xC3\xA6\xC3\xA7"
- "\xC3\xA8\xC3\xA9\xC3\xAA\xC3\xAB\xC3\xAC\xC3\xAD\xC3\xAE\xC3\xAF\xC3\xB0"
- "\xC3\xB1\xC3\xB2\xC3\xB3\xC3\xB4\xC3\xB5\xC3\xB6\xC3\xB7\xC3\xB8\xC3\xB9"
- "\xC3\xBA\xC3\xBB\xC3\xBC\xC3\xBD\xC3\xBE\xC3\xBF";
-
- std::string expected_output = "{\"all_chars\":\"" + all_chars_expected +
- "\"}";
- // Test JSONWriter interface
- std::string output_js;
- DictionaryValue valueRoot;
- valueRoot.SetString("all_chars", all_chars);
- JSONWriter::Write(valueRoot, &output_js);
- ASSERT_EQ(expected_output, output_js);
-
- // Test JSONValueSerializer interface (uses JSONWriter).
- JSONStringValueSerializer serializer(&output_js);
- ASSERT_TRUE(serializer.Serialize(valueRoot));
- ASSERT_EQ(expected_output, output_js);
-}
-
-TEST(JSONValueSerializerTest, UnicodeStrings) {
- // unicode string json -> escaped ascii text
- DictionaryValue root;
- string16 test(WideToUTF16(L"\x7F51\x9875"));
- root.SetString("web", test);
-
- static const char kExpected[] = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}";
-
- std::string actual;
- JSONStringValueSerializer serializer(&actual);
- ASSERT_TRUE(serializer.Serialize(root));
- ASSERT_EQ(kExpected, actual);
-
- // escaped ascii text -> json
- JSONStringValueDeserializer deserializer(kExpected);
- std::unique_ptr<Value> deserial_root =
- deserializer.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(deserial_root);
- DictionaryValue* dict_root =
- static_cast<DictionaryValue*>(deserial_root.get());
- string16 web_value;
- ASSERT_TRUE(dict_root->GetString("web", &web_value));
- ASSERT_EQ(test, web_value);
-}
-
-TEST(JSONValueSerializerTest, HexStrings) {
- // hex string json -> escaped ascii text
- DictionaryValue root;
- string16 test(WideToUTF16(L"\x01\x02"));
- root.SetString("test", test);
-
- static const char kExpected[] = "{\"test\":\"\\u0001\\u0002\"}";
-
- std::string actual;
- JSONStringValueSerializer serializer(&actual);
- ASSERT_TRUE(serializer.Serialize(root));
- ASSERT_EQ(kExpected, actual);
-
- // escaped ascii text -> json
- JSONStringValueDeserializer deserializer(kExpected);
- std::unique_ptr<Value> deserial_root =
- deserializer.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(deserial_root);
- DictionaryValue* dict_root =
- static_cast<DictionaryValue*>(deserial_root.get());
- string16 test_value;
- ASSERT_TRUE(dict_root->GetString("test", &test_value));
- ASSERT_EQ(test, test_value);
-
- // Test converting escaped regular chars
- static const char kEscapedChars[] = "{\"test\":\"\\u0067\\u006f\"}";
- JSONStringValueDeserializer deserializer2(kEscapedChars);
- deserial_root = deserializer2.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(deserial_root);
- dict_root = static_cast<DictionaryValue*>(deserial_root.get());
- ASSERT_TRUE(dict_root->GetString("test", &test_value));
- ASSERT_EQ(ASCIIToUTF16("go"), test_value);
-}
-
-TEST(JSONValueSerializerTest, JSONReaderComments) {
- ValidateJsonList("[ // 2, 3, ignore me ] \n1 ]");
- ValidateJsonList("[ /* 2, \n3, ignore me ]*/ \n1 ]");
- ValidateJsonList("//header\n[ // 2, \n// 3, \n1 ]// footer");
- ValidateJsonList("/*\n[ // 2, \n// 3, \n1 ]*/[1]");
- ValidateJsonList("[ 1 /* one */ ] /* end */");
- ValidateJsonList("[ 1 //// ,2\r\n ]");
-
- // It's ok to have a comment in a string.
- std::unique_ptr<ListValue> list =
- ListValue::From(JSONReader::Read("[\"// ok\\n /* foo */ \"]"));
- ASSERT_TRUE(list);
- ASSERT_EQ(1U, list->GetSize());
- Value* elt = nullptr;
- ASSERT_TRUE(list->Get(0, &elt));
- std::string value;
- ASSERT_TRUE(elt && elt->GetAsString(&value));
- ASSERT_EQ("// ok\n /* foo */ ", value);
-
- // You can't nest comments.
- ASSERT_FALSE(JSONReader::Read("/* /* inner */ outer */ [ 1 ]"));
-
- // Not a open comment token.
- ASSERT_FALSE(JSONReader::Read("/ * * / [1]"));
-}
-
-class JSONFileValueSerializerTest : public testing::Test {
- protected:
- void SetUp() override { ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); }
-
- ScopedTempDir temp_dir_;
-};
-
-TEST_F(JSONFileValueSerializerTest, Roundtrip) {
- FilePath original_file_path;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
- original_file_path = original_file_path.AppendASCII("serializer_test.json");
-
- ASSERT_TRUE(PathExists(original_file_path));
-
- JSONFileValueDeserializer deserializer(original_file_path);
- std::unique_ptr<DictionaryValue> root_dict =
- DictionaryValue::From(deserializer.Deserialize(nullptr, nullptr));
- ASSERT_TRUE(root_dict);
-
- Value* null_value = nullptr;
- ASSERT_TRUE(root_dict->Get("null", &null_value));
- ASSERT_TRUE(null_value);
- ASSERT_TRUE(null_value->is_none());
-
- bool bool_value = false;
- ASSERT_TRUE(root_dict->GetBoolean("bool", &bool_value));
- ASSERT_TRUE(bool_value);
-
- int int_value = 0;
- ASSERT_TRUE(root_dict->GetInteger("int", &int_value));
- ASSERT_EQ(42, int_value);
-
- std::string string_value;
- ASSERT_TRUE(root_dict->GetString("string", &string_value));
- ASSERT_EQ("hello", string_value);
-
- // Now try writing.
- const FilePath written_file_path =
- temp_dir_.GetPath().AppendASCII("test_output.js");
-
- ASSERT_FALSE(PathExists(written_file_path));
- JSONFileValueSerializer serializer(written_file_path);
- ASSERT_TRUE(serializer.Serialize(*root_dict));
- ASSERT_TRUE(PathExists(written_file_path));
-
- // Now compare file contents.
- EXPECT_TRUE(TextContentsEqual(original_file_path, written_file_path));
- EXPECT_TRUE(DeleteFile(written_file_path, false));
-}
-
-TEST_F(JSONFileValueSerializerTest, RoundtripNested) {
- FilePath original_file_path;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &original_file_path));
- original_file_path =
- original_file_path.AppendASCII("serializer_nested_test.json");
-
- ASSERT_TRUE(PathExists(original_file_path));
-
- JSONFileValueDeserializer deserializer(original_file_path);
- std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(root);
-
- // Now try writing.
- FilePath written_file_path =
- temp_dir_.GetPath().AppendASCII("test_output.json");
-
- ASSERT_FALSE(PathExists(written_file_path));
- JSONFileValueSerializer serializer(written_file_path);
- ASSERT_TRUE(serializer.Serialize(*root));
- ASSERT_TRUE(PathExists(written_file_path));
-
- // Now compare file contents.
- EXPECT_TRUE(TextContentsEqual(original_file_path, written_file_path));
- EXPECT_TRUE(DeleteFile(written_file_path, false));
-}
-
-TEST_F(JSONFileValueSerializerTest, NoWhitespace) {
- FilePath source_file_path;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &source_file_path));
- source_file_path =
- source_file_path.AppendASCII("serializer_test_nowhitespace.json");
- ASSERT_TRUE(PathExists(source_file_path));
- JSONFileValueDeserializer deserializer(source_file_path);
- std::unique_ptr<Value> root = deserializer.Deserialize(nullptr, nullptr);
- ASSERT_TRUE(root);
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/json/json_writer_unittest.cc b/base/json/json_writer_unittest.cc
deleted file mode 100644
index b90c3ea..0000000
--- a/base/json/json_writer_unittest.cc
+++ /dev/null
@@ -1,154 +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/json/json_writer.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/values.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(JSONWriterTest, BasicTypes) {
- std::string output_js;
-
- // Test null.
- EXPECT_TRUE(JSONWriter::Write(Value(), &output_js));
- EXPECT_EQ("null", output_js);
-
- // Test empty dict.
- EXPECT_TRUE(JSONWriter::Write(DictionaryValue(), &output_js));
- EXPECT_EQ("{}", output_js);
-
- // Test empty list.
- EXPECT_TRUE(JSONWriter::Write(ListValue(), &output_js));
- EXPECT_EQ("[]", output_js);
-
- // Test integer values.
- EXPECT_TRUE(JSONWriter::Write(Value(42), &output_js));
- EXPECT_EQ("42", output_js);
-
- // Test boolean values.
- EXPECT_TRUE(JSONWriter::Write(Value(true), &output_js));
- EXPECT_EQ("true", output_js);
-
- // Test Real values should always have a decimal or an 'e'.
- EXPECT_TRUE(JSONWriter::Write(Value(1.0), &output_js));
- EXPECT_EQ("1.0", output_js);
-
- // Test Real values in the the range (-1, 1) must have leading zeros
- EXPECT_TRUE(JSONWriter::Write(Value(0.2), &output_js));
- EXPECT_EQ("0.2", output_js);
-
- // Test Real values in the the range (-1, 1) must have leading zeros
- EXPECT_TRUE(JSONWriter::Write(Value(-0.8), &output_js));
- EXPECT_EQ("-0.8", output_js);
-
- // Test String values.
- EXPECT_TRUE(JSONWriter::Write(Value("foo"), &output_js));
- EXPECT_EQ("\"foo\"", output_js);
-}
-
-TEST(JSONWriterTest, NestedTypes) {
- std::string output_js;
-
- // Writer unittests like empty list/dict nesting,
- // list list nesting, etc.
- DictionaryValue root_dict;
- std::unique_ptr<ListValue> list(new ListValue());
- std::unique_ptr<DictionaryValue> inner_dict(new DictionaryValue());
- inner_dict->SetInteger("inner int", 10);
- list->Append(std::move(inner_dict));
- list->Append(std::make_unique<ListValue>());
- list->AppendBoolean(true);
- root_dict.Set("list", std::move(list));
-
- // Test the pretty-printer.
- EXPECT_TRUE(JSONWriter::Write(root_dict, &output_js));
- EXPECT_EQ("{\"list\":[{\"inner int\":10},[],true]}", output_js);
- EXPECT_TRUE(JSONWriter::WriteWithOptions(
- root_dict, JSONWriter::OPTIONS_PRETTY_PRINT, &output_js));
-
- // The pretty-printer uses a different newline style on Windows than on
- // other platforms.
-#if defined(OS_WIN)
-#define JSON_NEWLINE "\r\n"
-#else
-#define JSON_NEWLINE "\n"
-#endif
- EXPECT_EQ("{" JSON_NEWLINE
- " \"list\": [ {" JSON_NEWLINE
- " \"inner int\": 10" JSON_NEWLINE
- " }, [ ], true ]" JSON_NEWLINE
- "}" JSON_NEWLINE,
- output_js);
-#undef JSON_NEWLINE
-}
-
-TEST(JSONWriterTest, KeysWithPeriods) {
- std::string output_js;
-
- DictionaryValue period_dict;
- period_dict.SetKey("a.b", base::Value(3));
- period_dict.SetKey("c", base::Value(2));
- std::unique_ptr<DictionaryValue> period_dict2(new DictionaryValue());
- period_dict2->SetKey("g.h.i.j", base::Value(1));
- period_dict.SetWithoutPathExpansion("d.e.f", std::move(period_dict2));
- EXPECT_TRUE(JSONWriter::Write(period_dict, &output_js));
- EXPECT_EQ("{\"a.b\":3,\"c\":2,\"d.e.f\":{\"g.h.i.j\":1}}", output_js);
-
- DictionaryValue period_dict3;
- period_dict3.SetInteger("a.b", 2);
- period_dict3.SetKey("a.b", base::Value(1));
- EXPECT_TRUE(JSONWriter::Write(period_dict3, &output_js));
- EXPECT_EQ("{\"a\":{\"b\":2},\"a.b\":1}", output_js);
-}
-
-TEST(JSONWriterTest, BinaryValues) {
- std::string output_js;
-
- // Binary values should return errors unless suppressed via the
- // OPTIONS_OMIT_BINARY_VALUES flag.
- std::unique_ptr<Value> root(Value::CreateWithCopiedBuffer("asdf", 4));
- EXPECT_FALSE(JSONWriter::Write(*root, &output_js));
- EXPECT_TRUE(JSONWriter::WriteWithOptions(
- *root, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
- EXPECT_TRUE(output_js.empty());
-
- ListValue binary_list;
- binary_list.Append(Value::CreateWithCopiedBuffer("asdf", 4));
- binary_list.Append(std::make_unique<Value>(5));
- binary_list.Append(Value::CreateWithCopiedBuffer("asdf", 4));
- binary_list.Append(std::make_unique<Value>(2));
- binary_list.Append(Value::CreateWithCopiedBuffer("asdf", 4));
- EXPECT_FALSE(JSONWriter::Write(binary_list, &output_js));
- EXPECT_TRUE(JSONWriter::WriteWithOptions(
- binary_list, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
- EXPECT_EQ("[5,2]", output_js);
-
- DictionaryValue binary_dict;
- binary_dict.Set("a", Value::CreateWithCopiedBuffer("asdf", 4));
- binary_dict.SetInteger("b", 5);
- binary_dict.Set("c", Value::CreateWithCopiedBuffer("asdf", 4));
- binary_dict.SetInteger("d", 2);
- binary_dict.Set("e", Value::CreateWithCopiedBuffer("asdf", 4));
- EXPECT_FALSE(JSONWriter::Write(binary_dict, &output_js));
- EXPECT_TRUE(JSONWriter::WriteWithOptions(
- binary_dict, JSONWriter::OPTIONS_OMIT_BINARY_VALUES, &output_js));
- EXPECT_EQ("{\"b\":5,\"d\":2}", output_js);
-}
-
-TEST(JSONWriterTest, DoublesAsInts) {
- std::string output_js;
-
- // Test allowing a double with no fractional part to be written as an integer.
- Value double_value(1e10);
- EXPECT_TRUE(JSONWriter::WriteWithOptions(
- double_value, JSONWriter::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION,
- &output_js));
- EXPECT_EQ("10000000000", output_js);
-}
-
-} // namespace base
diff --git a/base/json/string_escape_unittest.cc b/base/json/string_escape_unittest.cc
deleted file mode 100644
index 1e962c6..0000000
--- a/base/json/string_escape_unittest.cc
+++ /dev/null
@@ -1,189 +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/json/string_escape.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(JSONStringEscapeTest, EscapeUTF8) {
- const struct {
- const char* to_escape;
- const char* escaped;
- } cases[] = {
- {"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
- {"a\b\f\n\r\t\v\1\\.\"z", "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
- {"b\x0f\x7f\xf0\xff!", // \xf0\xff is not a valid UTF-8 unit.
- "b\\u000F\x7F\xEF\xBF\xBD\xEF\xBF\xBD!"},
- {"c<>d", "c\\u003C>d"},
- {"Hello\xe2\x80\xa8world", "Hello\\u2028world"},
- {"\xe2\x80\xa9purple", "\\u2029purple"},
- {"\xF3\xBF\xBF\xBF", "\xEF\xBF\xBD"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- const char* in_ptr = cases[i].to_escape;
- std::string in_str = in_ptr;
-
- std::string out;
- EscapeJSONString(in_ptr, false, &out);
- EXPECT_EQ(std::string(cases[i].escaped), out);
- EXPECT_TRUE(IsStringUTF8(out));
-
- out.erase();
- bool convert_ok = EscapeJSONString(in_str, false, &out);
- EXPECT_EQ(std::string(cases[i].escaped), out);
- EXPECT_TRUE(IsStringUTF8(out));
-
- if (convert_ok) {
- std::string fooout = GetQuotedJSONString(in_str);
- EXPECT_EQ("\"" + std::string(cases[i].escaped) + "\"", fooout);
- EXPECT_TRUE(IsStringUTF8(out));
- }
- }
-
- std::string in = cases[0].to_escape;
- std::string out;
- EscapeJSONString(in, false, &out);
- EXPECT_TRUE(IsStringUTF8(out));
-
- // test quoting
- std::string out_quoted;
- EscapeJSONString(in, true, &out_quoted);
- EXPECT_EQ(out.length() + 2, out_quoted.length());
- EXPECT_EQ(out_quoted.find(out), 1U);
- EXPECT_TRUE(IsStringUTF8(out_quoted));
-
- // now try with a NULL in the string
- std::string null_prepend = "test";
- null_prepend.push_back(0);
- in = null_prepend + in;
- std::string expected = "test\\u0000";
- expected += cases[0].escaped;
- out.clear();
- EscapeJSONString(in, false, &out);
- EXPECT_EQ(expected, out);
- EXPECT_TRUE(IsStringUTF8(out));
-}
-
-TEST(JSONStringEscapeTest, EscapeUTF16) {
- const struct {
- const wchar_t* to_escape;
- const char* escaped;
- } cases[] = {
- {L"b\uffb1\u00ff", "b\xEF\xBE\xB1\xC3\xBF"},
- {L"\b\001aZ\"\\wee", "\\b\\u0001aZ\\\"\\\\wee"},
- {L"a\b\f\n\r\t\v\1\\.\"z",
- "a\\b\\f\\n\\r\\t\\u000B\\u0001\\\\.\\\"z"},
- {L"b\x0f\x7f\xf0\xff!", "b\\u000F\x7F\xC3\xB0\xC3\xBF!"},
- {L"c<>d", "c\\u003C>d"},
- {L"Hello\u2028world", "Hello\\u2028world"},
- {L"\u2029purple", "\\u2029purple"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- string16 in = WideToUTF16(cases[i].to_escape);
-
- std::string out;
- EscapeJSONString(in, false, &out);
- EXPECT_EQ(std::string(cases[i].escaped), out);
- EXPECT_TRUE(IsStringUTF8(out));
-
- out = GetQuotedJSONString(in);
- EXPECT_EQ("\"" + std::string(cases[i].escaped) + "\"", out);
- EXPECT_TRUE(IsStringUTF8(out));
- }
-
- string16 in = WideToUTF16(cases[0].to_escape);
- std::string out;
- EscapeJSONString(in, false, &out);
- EXPECT_TRUE(IsStringUTF8(out));
-
- // test quoting
- std::string out_quoted;
- EscapeJSONString(in, true, &out_quoted);
- EXPECT_EQ(out.length() + 2, out_quoted.length());
- EXPECT_EQ(out_quoted.find(out), 1U);
- EXPECT_TRUE(IsStringUTF8(out));
-
- // now try with a NULL in the string
- string16 null_prepend = WideToUTF16(L"test");
- null_prepend.push_back(0);
- in = null_prepend + in;
- std::string expected = "test\\u0000";
- expected += cases[0].escaped;
- out.clear();
- EscapeJSONString(in, false, &out);
- EXPECT_EQ(expected, out);
- EXPECT_TRUE(IsStringUTF8(out));
-}
-
-TEST(JSONStringEscapeTest, EscapeUTF16OutsideBMP) {
- {
- // {a, U+10300, !}, SMP.
- string16 test;
- test.push_back('a');
- test.push_back(0xD800);
- test.push_back(0xDF00);
- test.push_back('!');
- std::string actual;
- EXPECT_TRUE(EscapeJSONString(test, false, &actual));
- EXPECT_EQ("a\xF0\x90\x8C\x80!", actual);
- }
- {
- // {U+20021, U+2002B}, SIP.
- string16 test;
- test.push_back(0xD840);
- test.push_back(0xDC21);
- test.push_back(0xD840);
- test.push_back(0xDC2B);
- std::string actual;
- EXPECT_TRUE(EscapeJSONString(test, false, &actual));
- EXPECT_EQ("\xF0\xA0\x80\xA1\xF0\xA0\x80\xAB", actual);
- }
- {
- // {?, U+D800, @}, lone surrogate.
- string16 test;
- test.push_back('?');
- test.push_back(0xD800);
- test.push_back('@');
- std::string actual;
- EXPECT_FALSE(EscapeJSONString(test, false, &actual));
- EXPECT_EQ("?\xEF\xBF\xBD@", actual);
- }
-}
-
-TEST(JSONStringEscapeTest, EscapeBytes) {
- const struct {
- const char* to_escape;
- const char* escaped;
- } cases[] = {
- {"b\x0f\x7f\xf0\xff!", "b\\u000F\\u007F\\u00F0\\u00FF!"},
- {"\xe5\xc4\x4f\x05\xb6\xfd", "\\u00E5\\u00C4O\\u0005\\u00B6\\u00FD"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- std::string in = std::string(cases[i].to_escape);
- EXPECT_FALSE(IsStringUTF8(in));
-
- EXPECT_EQ(std::string(cases[i].escaped),
- EscapeBytesAsInvalidJSONString(in, false));
- EXPECT_EQ("\"" + std::string(cases[i].escaped) + "\"",
- EscapeBytesAsInvalidJSONString(in, true));
- }
-
- const char kEmbedNull[] = { '\xab', '\x39', '\0', '\x9f', '\xab' };
- std::string in(kEmbedNull, arraysize(kEmbedNull));
- EXPECT_FALSE(IsStringUTF8(in));
- EXPECT_EQ(std::string("\\u00AB9\\u0000\\u009F\\u00AB"),
- EscapeBytesAsInvalidJSONString(in, false));
-}
-
-} // namespace base
diff --git a/base/lazy_instance_unittest.cc b/base/lazy_instance_unittest.cc
deleted file mode 100644
index 242e8b5..0000000
--- a/base/lazy_instance_unittest.cc
+++ /dev/null
@@ -1,322 +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 <memory>
-#include <vector>
-
-#include "base/at_exit.h"
-#include "base/atomic_sequence_num.h"
-#include "base/atomicops.h"
-#include "base/barrier_closure.h"
-#include "base/bind.h"
-#include "base/lazy_instance.h"
-#include "base/sys_info.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-base::AtomicSequenceNumber constructed_seq_;
-base::AtomicSequenceNumber destructed_seq_;
-
-class ConstructAndDestructLogger {
- public:
- ConstructAndDestructLogger() {
- constructed_seq_.GetNext();
- }
- ~ConstructAndDestructLogger() {
- destructed_seq_.GetNext();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ConstructAndDestructLogger);
-};
-
-class SlowConstructor {
- public:
- SlowConstructor() : some_int_(0) {
- // Sleep for 1 second to try to cause a race.
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(1));
- ++constructed;
- some_int_ = 12;
- }
- int some_int() const { return some_int_; }
-
- static int constructed;
- private:
- int some_int_;
-
- DISALLOW_COPY_AND_ASSIGN(SlowConstructor);
-};
-
-// static
-int SlowConstructor::constructed = 0;
-
-class SlowDelegate : public base::DelegateSimpleThread::Delegate {
- public:
- explicit SlowDelegate(
- base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy)
- : lazy_(lazy) {}
-
- void Run() override {
- EXPECT_EQ(12, lazy_->Get().some_int());
- EXPECT_EQ(12, lazy_->Pointer()->some_int());
- }
-
- private:
- base::LazyInstance<SlowConstructor>::DestructorAtExit* lazy_;
-
- DISALLOW_COPY_AND_ASSIGN(SlowDelegate);
-};
-
-} // namespace
-
-base::LazyInstance<ConstructAndDestructLogger>::DestructorAtExit lazy_logger =
- LAZY_INSTANCE_INITIALIZER;
-
-TEST(LazyInstanceTest, Basic) {
- {
- base::ShadowingAtExitManager shadow;
-
- EXPECT_FALSE(lazy_logger.IsCreated());
- EXPECT_EQ(0, constructed_seq_.GetNext());
- EXPECT_EQ(0, destructed_seq_.GetNext());
-
- lazy_logger.Get();
- EXPECT_TRUE(lazy_logger.IsCreated());
- EXPECT_EQ(2, constructed_seq_.GetNext());
- EXPECT_EQ(1, destructed_seq_.GetNext());
-
- lazy_logger.Pointer();
- EXPECT_TRUE(lazy_logger.IsCreated());
- EXPECT_EQ(3, constructed_seq_.GetNext());
- EXPECT_EQ(2, destructed_seq_.GetNext());
- }
- EXPECT_FALSE(lazy_logger.IsCreated());
- EXPECT_EQ(4, constructed_seq_.GetNext());
- EXPECT_EQ(4, destructed_seq_.GetNext());
-}
-
-base::LazyInstance<SlowConstructor>::DestructorAtExit lazy_slow =
- LAZY_INSTANCE_INITIALIZER;
-
-TEST(LazyInstanceTest, ConstructorThreadSafety) {
- {
- base::ShadowingAtExitManager shadow;
-
- SlowDelegate delegate(&lazy_slow);
- EXPECT_EQ(0, SlowConstructor::constructed);
-
- base::DelegateSimpleThreadPool pool("lazy_instance_cons", 5);
- pool.AddWork(&delegate, 20);
- EXPECT_EQ(0, SlowConstructor::constructed);
-
- pool.Start();
- pool.JoinAll();
- EXPECT_EQ(1, SlowConstructor::constructed);
- }
-}
-
-namespace {
-
-// DeleteLogger is an object which sets a flag when it's destroyed.
-// It accepts a bool* and sets the bool to true when the dtor runs.
-class DeleteLogger {
- public:
- DeleteLogger() : deleted_(nullptr) {}
- ~DeleteLogger() { *deleted_ = true; }
-
- void SetDeletedPtr(bool* deleted) {
- deleted_ = deleted;
- }
-
- private:
- bool* deleted_;
-};
-
-} // anonymous namespace
-
-TEST(LazyInstanceTest, LeakyLazyInstance) {
- // Check that using a plain LazyInstance causes the dtor to run
- // when the AtExitManager finishes.
- bool deleted1 = false;
- {
- base::ShadowingAtExitManager shadow;
- static base::LazyInstance<DeleteLogger>::DestructorAtExit test =
- LAZY_INSTANCE_INITIALIZER;
- test.Get().SetDeletedPtr(&deleted1);
- }
- EXPECT_TRUE(deleted1);
-
- // Check that using a *leaky* LazyInstance makes the dtor not run
- // when the AtExitManager finishes.
- bool deleted2 = false;
- {
- base::ShadowingAtExitManager shadow;
- static base::LazyInstance<DeleteLogger>::Leaky
- test = LAZY_INSTANCE_INITIALIZER;
- test.Get().SetDeletedPtr(&deleted2);
- }
- EXPECT_FALSE(deleted2);
-}
-
-namespace {
-
-template <size_t alignment>
-class AlignedData {
- public:
- AlignedData() = default;
- ~AlignedData() = default;
- alignas(alignment) char data_[alignment];
-};
-
-} // namespace
-
-#define EXPECT_ALIGNED(ptr, align) \
- EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
-
-TEST(LazyInstanceTest, Alignment) {
- using base::LazyInstance;
-
- // Create some static instances with increasing sizes and alignment
- // requirements. By ordering this way, the linker will need to do some work to
- // ensure proper alignment of the static data.
- static LazyInstance<AlignedData<4>>::DestructorAtExit align4 =
- LAZY_INSTANCE_INITIALIZER;
- static LazyInstance<AlignedData<32>>::DestructorAtExit align32 =
- LAZY_INSTANCE_INITIALIZER;
- static LazyInstance<AlignedData<4096>>::DestructorAtExit align4096 =
- LAZY_INSTANCE_INITIALIZER;
-
- EXPECT_ALIGNED(align4.Pointer(), 4);
- EXPECT_ALIGNED(align32.Pointer(), 32);
- EXPECT_ALIGNED(align4096.Pointer(), 4096);
-}
-
-namespace {
-
-// A class whose constructor busy-loops until it is told to complete
-// construction.
-class BlockingConstructor {
- public:
- BlockingConstructor() {
- EXPECT_FALSE(WasConstructorCalled());
- base::subtle::NoBarrier_Store(&constructor_called_, 1);
- EXPECT_TRUE(WasConstructorCalled());
- while (!base::subtle::NoBarrier_Load(&complete_construction_))
- base::PlatformThread::YieldCurrentThread();
- done_construction_ = true;
- }
-
- ~BlockingConstructor() {
- // Restore static state for the next test.
- base::subtle::NoBarrier_Store(&constructor_called_, 0);
- base::subtle::NoBarrier_Store(&complete_construction_, 0);
- }
-
- // Returns true if BlockingConstructor() was entered.
- static bool WasConstructorCalled() {
- return base::subtle::NoBarrier_Load(&constructor_called_);
- }
-
- // Instructs BlockingConstructor() that it may now unblock its construction.
- static void CompleteConstructionNow() {
- base::subtle::NoBarrier_Store(&complete_construction_, 1);
- }
-
- bool done_construction() { return done_construction_; }
-
- private:
- // Use Atomic32 instead of AtomicFlag for them to be trivially initialized.
- static base::subtle::Atomic32 constructor_called_;
- static base::subtle::Atomic32 complete_construction_;
-
- bool done_construction_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(BlockingConstructor);
-};
-
-// A SimpleThread running at |thread_priority| which invokes |before_get|
-// (optional) and then invokes Get() on the LazyInstance it's assigned.
-class BlockingConstructorThread : public base::SimpleThread {
- public:
- BlockingConstructorThread(
- base::ThreadPriority thread_priority,
- base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy,
- base::OnceClosure before_get)
- : SimpleThread("BlockingConstructorThread", Options(thread_priority)),
- lazy_(lazy),
- before_get_(std::move(before_get)) {}
-
- void Run() override {
- if (before_get_)
- std::move(before_get_).Run();
- EXPECT_TRUE(lazy_->Get().done_construction());
- }
-
- private:
- base::LazyInstance<BlockingConstructor>::DestructorAtExit* lazy_;
- base::OnceClosure before_get_;
-
- DISALLOW_COPY_AND_ASSIGN(BlockingConstructorThread);
-};
-
-// static
-base::subtle::Atomic32 BlockingConstructor::constructor_called_ = 0;
-// static
-base::subtle::Atomic32 BlockingConstructor::complete_construction_ = 0;
-
-base::LazyInstance<BlockingConstructor>::DestructorAtExit lazy_blocking =
- LAZY_INSTANCE_INITIALIZER;
-
-} // namespace
-
-// Tests that if the thread assigned to construct the LazyInstance runs at
-// background priority : the foreground threads will yield to it enough for it
-// to eventually complete construction.
-// This is a regression test for https://crbug.com/797129.
-TEST(LazyInstanceTest, PriorityInversionAtInitializationResolves) {
- base::TimeTicks test_begin = base::TimeTicks::Now();
-
- // Construct BlockingConstructor from a background thread.
- BlockingConstructorThread background_getter(
- base::ThreadPriority::BACKGROUND, &lazy_blocking, base::OnceClosure());
- background_getter.Start();
-
- while (!BlockingConstructor::WasConstructorCalled())
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(1));
-
- // Spin 4 foreground thread per core contending to get the already under
- // construction LazyInstance. When they are all running and poking at it :
- // allow the background thread to complete its work.
- const int kNumForegroundThreads = 4 * base::SysInfo::NumberOfProcessors();
- std::vector<std::unique_ptr<base::SimpleThread>> foreground_threads;
- base::RepeatingClosure foreground_thread_ready_callback =
- base::BarrierClosure(
- kNumForegroundThreads,
- base::BindOnce(&BlockingConstructor::CompleteConstructionNow));
- for (int i = 0; i < kNumForegroundThreads; ++i) {
- foreground_threads.push_back(std::make_unique<BlockingConstructorThread>(
- base::ThreadPriority::NORMAL, &lazy_blocking,
- foreground_thread_ready_callback));
- foreground_threads.back()->Start();
- }
-
- // This test will hang if the foreground threads become stuck in
- // LazyInstance::Get() per the background thread never being scheduled to
- // complete construction.
- for (auto& foreground_thread : foreground_threads)
- foreground_thread->Join();
- background_getter.Join();
-
- // Fail if this test takes more than 5 seconds (it takes 5-10 seconds on a
- // Z840 without r527445 but is expected to be fast (~30ms) with the fix).
- EXPECT_LT(base::TimeTicks::Now() - test_begin,
- base::TimeDelta::FromSeconds(5));
-}
diff --git a/base/logging_unittest.cc b/base/logging_unittest.cc
deleted file mode 100644
index 0264012..0000000
--- a/base/logging_unittest.cc
+++ /dev/null
@@ -1,676 +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/logging.h"
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/test/scoped_feature_list.h"
-#include "build_config.h"
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <signal.h>
-#include <unistd.h>
-#include "base/posix/eintr_wrapper.h"
-#endif // OS_POSIX
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#include <ucontext.h>
-#endif
-
-#if defined(OS_WIN)
-#include <excpt.h>
-#include <windows.h>
-#endif // OS_WIN
-
-#if defined(OS_FUCHSIA)
-#include "base/fuchsia/fuchsia_logging.h"
-#endif
-
-namespace logging {
-
-namespace {
-
-using ::testing::Return;
-using ::testing::_;
-
-// Needs to be global since log assert handlers can't maintain state.
-int g_log_sink_call_count = 0;
-
-#if !defined(OFFICIAL_BUILD) || defined(DCHECK_ALWAYS_ON) || !defined(NDEBUG)
-void LogSink(const char* file,
- int line,
- const base::StringPiece message,
- const base::StringPiece stack_trace) {
- ++g_log_sink_call_count;
-}
-#endif
-
-// Class to make sure any manipulations we do to the min log level are
-// contained (i.e., do not affect other unit tests).
-class LogStateSaver {
- public:
- LogStateSaver() : old_min_log_level_(GetMinLogLevel()) {}
-
- ~LogStateSaver() {
- SetMinLogLevel(old_min_log_level_);
- g_log_sink_call_count = 0;
- }
-
- private:
- int old_min_log_level_;
-
- DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
-};
-
-class LoggingTest : public testing::Test {
- private:
- LogStateSaver log_state_saver_;
-};
-
-class MockLogSource {
- public:
- MOCK_METHOD0(Log, const char*());
-};
-
-class MockLogAssertHandler {
- public:
- MOCK_METHOD4(
- HandleLogAssert,
- void(const char*, int, const base::StringPiece, const base::StringPiece));
-};
-
-TEST_F(LoggingTest, BasicLogging) {
- MockLogSource mock_log_source;
- EXPECT_CALL(mock_log_source, Log())
- .Times(DCHECK_IS_ON() ? 16 : 8)
- .WillRepeatedly(Return("log message"));
-
- SetMinLogLevel(LOG_INFO);
-
- EXPECT_TRUE(LOG_IS_ON(INFO));
- EXPECT_TRUE((DCHECK_IS_ON() != 0) == DLOG_IS_ON(INFO));
- EXPECT_TRUE(VLOG_IS_ON(0));
-
- LOG(INFO) << mock_log_source.Log();
- LOG_IF(INFO, true) << mock_log_source.Log();
- PLOG(INFO) << mock_log_source.Log();
- PLOG_IF(INFO, true) << mock_log_source.Log();
- VLOG(0) << mock_log_source.Log();
- VLOG_IF(0, true) << mock_log_source.Log();
- VPLOG(0) << mock_log_source.Log();
- VPLOG_IF(0, true) << mock_log_source.Log();
-
- DLOG(INFO) << mock_log_source.Log();
- DLOG_IF(INFO, true) << mock_log_source.Log();
- DPLOG(INFO) << mock_log_source.Log();
- DPLOG_IF(INFO, true) << mock_log_source.Log();
- DVLOG(0) << mock_log_source.Log();
- DVLOG_IF(0, true) << mock_log_source.Log();
- DVPLOG(0) << mock_log_source.Log();
- DVPLOG_IF(0, true) << mock_log_source.Log();
-}
-
-TEST_F(LoggingTest, LogIsOn) {
-#if defined(NDEBUG)
- const bool kDfatalIsFatal = false;
-#else // defined(NDEBUG)
- const bool kDfatalIsFatal = true;
-#endif // defined(NDEBUG)
-
- SetMinLogLevel(LOG_INFO);
- EXPECT_TRUE(LOG_IS_ON(INFO));
- EXPECT_TRUE(LOG_IS_ON(WARNING));
- EXPECT_TRUE(LOG_IS_ON(ERROR));
- EXPECT_TRUE(LOG_IS_ON(FATAL));
- EXPECT_TRUE(LOG_IS_ON(DFATAL));
-
- SetMinLogLevel(LOG_WARNING);
- EXPECT_FALSE(LOG_IS_ON(INFO));
- EXPECT_TRUE(LOG_IS_ON(WARNING));
- EXPECT_TRUE(LOG_IS_ON(ERROR));
- EXPECT_TRUE(LOG_IS_ON(FATAL));
- EXPECT_TRUE(LOG_IS_ON(DFATAL));
-
- SetMinLogLevel(LOG_ERROR);
- EXPECT_FALSE(LOG_IS_ON(INFO));
- EXPECT_FALSE(LOG_IS_ON(WARNING));
- EXPECT_TRUE(LOG_IS_ON(ERROR));
- EXPECT_TRUE(LOG_IS_ON(FATAL));
- EXPECT_TRUE(LOG_IS_ON(DFATAL));
-
- // LOG_IS_ON(FATAL) should always be true.
- SetMinLogLevel(LOG_FATAL + 1);
- EXPECT_FALSE(LOG_IS_ON(INFO));
- EXPECT_FALSE(LOG_IS_ON(WARNING));
- EXPECT_FALSE(LOG_IS_ON(ERROR));
- EXPECT_TRUE(LOG_IS_ON(FATAL));
- EXPECT_EQ(kDfatalIsFatal, LOG_IS_ON(DFATAL));
-}
-
-TEST_F(LoggingTest, LoggingIsLazyBySeverity) {
- MockLogSource mock_log_source;
- EXPECT_CALL(mock_log_source, Log()).Times(0);
-
- SetMinLogLevel(LOG_WARNING);
-
- EXPECT_FALSE(LOG_IS_ON(INFO));
- EXPECT_FALSE(DLOG_IS_ON(INFO));
- EXPECT_FALSE(VLOG_IS_ON(1));
-
- LOG(INFO) << mock_log_source.Log();
- LOG_IF(INFO, false) << mock_log_source.Log();
- PLOG(INFO) << mock_log_source.Log();
- PLOG_IF(INFO, false) << mock_log_source.Log();
- VLOG(1) << mock_log_source.Log();
- VLOG_IF(1, true) << mock_log_source.Log();
- VPLOG(1) << mock_log_source.Log();
- VPLOG_IF(1, true) << mock_log_source.Log();
-
- DLOG(INFO) << mock_log_source.Log();
- DLOG_IF(INFO, true) << mock_log_source.Log();
- DPLOG(INFO) << mock_log_source.Log();
- DPLOG_IF(INFO, true) << mock_log_source.Log();
- DVLOG(1) << mock_log_source.Log();
- DVLOG_IF(1, true) << mock_log_source.Log();
- DVPLOG(1) << mock_log_source.Log();
- DVPLOG_IF(1, true) << mock_log_source.Log();
-}
-
-TEST_F(LoggingTest, LoggingIsLazyByDestination) {
- MockLogSource mock_log_source;
- MockLogSource mock_log_source_error;
- EXPECT_CALL(mock_log_source, Log()).Times(0);
-
- // Severity >= ERROR is always printed to stderr.
- EXPECT_CALL(mock_log_source_error, Log()).Times(1).
- WillRepeatedly(Return("log message"));
-
- LoggingSettings settings;
- settings.logging_dest = LOG_NONE;
- InitLogging(settings);
-
- LOG(INFO) << mock_log_source.Log();
- LOG(WARNING) << mock_log_source.Log();
- LOG(ERROR) << mock_log_source_error.Log();
-}
-
-// Official builds have CHECKs directly call BreakDebugger.
-#if !defined(OFFICIAL_BUILD)
-
-// https://crbug.com/709067 tracks test flakiness on iOS.
-#if defined(OS_IOS)
-#define MAYBE_CheckStreamsAreLazy DISABLED_CheckStreamsAreLazy
-#else
-#define MAYBE_CheckStreamsAreLazy CheckStreamsAreLazy
-#endif
-TEST_F(LoggingTest, MAYBE_CheckStreamsAreLazy) {
- MockLogSource mock_log_source, uncalled_mock_log_source;
- EXPECT_CALL(mock_log_source, Log()).Times(8).
- WillRepeatedly(Return("check message"));
- EXPECT_CALL(uncalled_mock_log_source, Log()).Times(0);
-
- ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
-
- CHECK(mock_log_source.Log()) << uncalled_mock_log_source.Log();
- PCHECK(!mock_log_source.Log()) << mock_log_source.Log();
- CHECK_EQ(mock_log_source.Log(), mock_log_source.Log())
- << uncalled_mock_log_source.Log();
- CHECK_NE(mock_log_source.Log(), mock_log_source.Log())
- << mock_log_source.Log();
-}
-
-#endif
-
-#if defined(OFFICIAL_BUILD) && defined(OS_WIN)
-NOINLINE void CheckContainingFunc(int death_location) {
- CHECK(death_location != 1);
- CHECK(death_location != 2);
- CHECK(death_location != 3);
-}
-
-int GetCheckExceptionData(EXCEPTION_POINTERS* p, DWORD* code, void** addr) {
- *code = p->ExceptionRecord->ExceptionCode;
- *addr = p->ExceptionRecord->ExceptionAddress;
- return EXCEPTION_EXECUTE_HANDLER;
-}
-
-TEST_F(LoggingTest, CheckCausesDistinctBreakpoints) {
- DWORD code1 = 0;
- DWORD code2 = 0;
- DWORD code3 = 0;
- void* addr1 = nullptr;
- void* addr2 = nullptr;
- void* addr3 = nullptr;
-
- // Record the exception code and addresses.
- __try {
- CheckContainingFunc(1);
- } __except (
- GetCheckExceptionData(GetExceptionInformation(), &code1, &addr1)) {
- }
-
- __try {
- CheckContainingFunc(2);
- } __except (
- GetCheckExceptionData(GetExceptionInformation(), &code2, &addr2)) {
- }
-
- __try {
- CheckContainingFunc(3);
- } __except (
- GetCheckExceptionData(GetExceptionInformation(), &code3, &addr3)) {
- }
-
- // Ensure that the exception codes are correct (in particular, breakpoints,
- // not access violations).
- EXPECT_EQ(STATUS_BREAKPOINT, code1);
- EXPECT_EQ(STATUS_BREAKPOINT, code2);
- EXPECT_EQ(STATUS_BREAKPOINT, code3);
-
- // Ensure that none of the CHECKs are colocated.
- EXPECT_NE(addr1, addr2);
- EXPECT_NE(addr1, addr3);
- EXPECT_NE(addr2, addr3);
-}
-
-#elif defined(OS_POSIX) && !defined(OS_NACL) && !defined(OS_IOS) && \
- !defined(OS_FUCHSIA) && \
- (defined(ARCH_CPU_X86_FAMILY) || defined(ARCH_CPU_ARM_FAMILY))
-
-int g_child_crash_pipe;
-
-void CheckCrashTestSighandler(int, siginfo_t* info, void* context_ptr) {
- // Conversely to what clearly stated in "man 2 sigaction", some Linux kernels
- // do NOT populate the |info->si_addr| in the case of a SIGTRAP. Hence we
- // need the arch-specific boilerplate below, which is inspired by breakpad.
- // At the same time, on OSX, ucontext.h is deprecated but si_addr works fine.
- uintptr_t crash_addr = 0;
-#if defined(OS_MACOSX)
- crash_addr = reinterpret_cast<uintptr_t>(info->si_addr);
-#else // OS_POSIX && !OS_MACOSX
- ucontext_t* context = reinterpret_cast<ucontext_t*>(context_ptr);
-#if defined(ARCH_CPU_X86)
- crash_addr = static_cast<uintptr_t>(context->uc_mcontext.gregs[REG_EIP]);
-#elif defined(ARCH_CPU_X86_64)
- crash_addr = static_cast<uintptr_t>(context->uc_mcontext.gregs[REG_RIP]);
-#elif defined(ARCH_CPU_ARMEL)
- crash_addr = static_cast<uintptr_t>(context->uc_mcontext.arm_pc);
-#elif defined(ARCH_CPU_ARM64)
- crash_addr = static_cast<uintptr_t>(context->uc_mcontext.pc);
-#endif // ARCH_*
-#endif // OS_POSIX && !OS_MACOSX
- HANDLE_EINTR(write(g_child_crash_pipe, &crash_addr, sizeof(uintptr_t)));
- _exit(0);
-}
-
-// CHECK causes a direct crash (without jumping to another function) only in
-// official builds. Unfortunately, continuous test coverage on official builds
-// is lower. DO_CHECK here falls back on a home-brewed implementation in
-// non-official builds, to catch regressions earlier in the CQ.
-#if defined(OFFICIAL_BUILD)
-#define DO_CHECK CHECK
-#else
-#define DO_CHECK(cond) \
- if (!(cond)) \
- IMMEDIATE_CRASH()
-#endif
-
-void CrashChildMain(int death_location) {
- struct sigaction act = {};
- act.sa_sigaction = CheckCrashTestSighandler;
- act.sa_flags = SA_SIGINFO;
- ASSERT_EQ(0, sigaction(SIGTRAP, &act, nullptr));
- ASSERT_EQ(0, sigaction(SIGBUS, &act, nullptr));
- ASSERT_EQ(0, sigaction(SIGILL, &act, nullptr));
- DO_CHECK(death_location != 1);
- DO_CHECK(death_location != 2);
- printf("\n");
- DO_CHECK(death_location != 3);
-
- // Should never reach this point.
- const uintptr_t failed = 0;
- HANDLE_EINTR(write(g_child_crash_pipe, &failed, sizeof(uintptr_t)));
-};
-
-void SpawnChildAndCrash(int death_location, uintptr_t* child_crash_addr) {
- int pipefd[2];
- ASSERT_EQ(0, pipe(pipefd));
-
- int pid = fork();
- ASSERT_GE(pid, 0);
-
- if (pid == 0) { // child process.
- close(pipefd[0]); // Close reader (parent) end.
- g_child_crash_pipe = pipefd[1];
- CrashChildMain(death_location);
- FAIL() << "The child process was supposed to crash. It didn't.";
- }
-
- close(pipefd[1]); // Close writer (child) end.
- DCHECK(child_crash_addr);
- int res = HANDLE_EINTR(read(pipefd[0], child_crash_addr, sizeof(uintptr_t)));
- ASSERT_EQ(static_cast<int>(sizeof(uintptr_t)), res);
-}
-
-TEST_F(LoggingTest, CheckCausesDistinctBreakpoints) {
- uintptr_t child_crash_addr_1 = 0;
- uintptr_t child_crash_addr_2 = 0;
- uintptr_t child_crash_addr_3 = 0;
-
- SpawnChildAndCrash(1, &child_crash_addr_1);
- SpawnChildAndCrash(2, &child_crash_addr_2);
- SpawnChildAndCrash(3, &child_crash_addr_3);
-
- ASSERT_NE(0u, child_crash_addr_1);
- ASSERT_NE(0u, child_crash_addr_2);
- ASSERT_NE(0u, child_crash_addr_3);
- ASSERT_NE(child_crash_addr_1, child_crash_addr_2);
- ASSERT_NE(child_crash_addr_1, child_crash_addr_3);
- ASSERT_NE(child_crash_addr_2, child_crash_addr_3);
-}
-#endif // OS_POSIX
-
-TEST_F(LoggingTest, DebugLoggingReleaseBehavior) {
-#if DCHECK_IS_ON()
- int debug_only_variable = 1;
-#endif
- // These should avoid emitting references to |debug_only_variable|
- // in release mode.
- DLOG_IF(INFO, debug_only_variable) << "test";
- DLOG_ASSERT(debug_only_variable) << "test";
- DPLOG_IF(INFO, debug_only_variable) << "test";
- DVLOG_IF(1, debug_only_variable) << "test";
-}
-
-TEST_F(LoggingTest, DcheckStreamsAreLazy) {
- MockLogSource mock_log_source;
- EXPECT_CALL(mock_log_source, Log()).Times(0);
-#if DCHECK_IS_ON()
- DCHECK(true) << mock_log_source.Log();
- DCHECK_EQ(0, 0) << mock_log_source.Log();
-#else
- DCHECK(mock_log_source.Log()) << mock_log_source.Log();
- DPCHECK(mock_log_source.Log()) << mock_log_source.Log();
- DCHECK_EQ(0, 0) << mock_log_source.Log();
- DCHECK_EQ(mock_log_source.Log(), static_cast<const char*>(nullptr))
- << mock_log_source.Log();
-#endif
-}
-
-void DcheckEmptyFunction1() {
- // Provide a body so that Release builds do not cause the compiler to
- // optimize DcheckEmptyFunction1 and DcheckEmptyFunction2 as a single
- // function, which breaks the Dcheck tests below.
- LOG(INFO) << "DcheckEmptyFunction1";
-}
-void DcheckEmptyFunction2() {}
-
-#if DCHECK_IS_CONFIGURABLE
-class ScopedDcheckSeverity {
- public:
- ScopedDcheckSeverity(LogSeverity new_severity) : old_severity_(LOG_DCHECK) {
- LOG_DCHECK = new_severity;
- }
-
- ~ScopedDcheckSeverity() { LOG_DCHECK = old_severity_; }
-
- private:
- LogSeverity old_severity_;
-};
-#endif // DCHECK_IS_CONFIGURABLE
-
-// https://crbug.com/709067 tracks test flakiness on iOS.
-#if defined(OS_IOS)
-#define MAYBE_Dcheck DISABLED_Dcheck
-#else
-#define MAYBE_Dcheck Dcheck
-#endif
-TEST_F(LoggingTest, MAYBE_Dcheck) {
-#if DCHECK_IS_CONFIGURABLE
- // DCHECKs are enabled, and LOG_DCHECK is mutable, but defaults to non-fatal.
- // Set it to LOG_FATAL to get the expected behavior from the rest of this
- // test.
- ScopedDcheckSeverity dcheck_severity(LOG_FATAL);
-#endif // DCHECK_IS_CONFIGURABLE
-
-#if defined(NDEBUG) && !defined(DCHECK_ALWAYS_ON)
- // Release build.
- EXPECT_FALSE(DCHECK_IS_ON());
- EXPECT_FALSE(DLOG_IS_ON(DCHECK));
-#elif defined(NDEBUG) && defined(DCHECK_ALWAYS_ON)
- // Release build with real DCHECKS.
- ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
- EXPECT_TRUE(DCHECK_IS_ON());
- EXPECT_TRUE(DLOG_IS_ON(DCHECK));
-#else
- // Debug build.
- ScopedLogAssertHandler scoped_assert_handler(base::Bind(LogSink));
- EXPECT_TRUE(DCHECK_IS_ON());
- EXPECT_TRUE(DLOG_IS_ON(DCHECK));
-#endif
-
- // DCHECKs are fatal iff they're compiled in DCHECK_IS_ON() and the DCHECK
- // log level is set to fatal.
- const bool dchecks_are_fatal = DCHECK_IS_ON() && LOG_DCHECK == LOG_FATAL;
- EXPECT_EQ(0, g_log_sink_call_count);
- DCHECK(false);
- EXPECT_EQ(dchecks_are_fatal ? 1 : 0, g_log_sink_call_count);
- DPCHECK(false);
- EXPECT_EQ(dchecks_are_fatal ? 2 : 0, g_log_sink_call_count);
- DCHECK_EQ(0, 1);
- EXPECT_EQ(dchecks_are_fatal ? 3 : 0, g_log_sink_call_count);
-
- // Test DCHECK on std::nullptr_t
- g_log_sink_call_count = 0;
- const void* p_null = nullptr;
- const void* p_not_null = &p_null;
- DCHECK_EQ(p_null, nullptr);
- DCHECK_EQ(nullptr, p_null);
- DCHECK_NE(p_not_null, nullptr);
- DCHECK_NE(nullptr, p_not_null);
- EXPECT_EQ(0, g_log_sink_call_count);
-
- // Test DCHECK on a scoped enum.
- enum class Animal { DOG, CAT };
- DCHECK_EQ(Animal::DOG, Animal::DOG);
- EXPECT_EQ(0, g_log_sink_call_count);
- DCHECK_EQ(Animal::DOG, Animal::CAT);
- EXPECT_EQ(dchecks_are_fatal ? 1 : 0, g_log_sink_call_count);
-
- // Test DCHECK on functions and function pointers.
- g_log_sink_call_count = 0;
- struct MemberFunctions {
- void MemberFunction1() {
- // See the comment in DcheckEmptyFunction1().
- LOG(INFO) << "Do not merge with MemberFunction2.";
- }
- void MemberFunction2() {}
- };
- void (MemberFunctions::*mp1)() = &MemberFunctions::MemberFunction1;
- void (MemberFunctions::*mp2)() = &MemberFunctions::MemberFunction2;
- void (*fp1)() = DcheckEmptyFunction1;
- void (*fp2)() = DcheckEmptyFunction2;
- void (*fp3)() = DcheckEmptyFunction1;
- DCHECK_EQ(fp1, fp3);
- EXPECT_EQ(0, g_log_sink_call_count);
- DCHECK_EQ(mp1, &MemberFunctions::MemberFunction1);
- EXPECT_EQ(0, g_log_sink_call_count);
- DCHECK_EQ(mp2, &MemberFunctions::MemberFunction2);
- EXPECT_EQ(0, g_log_sink_call_count);
- DCHECK_EQ(fp1, fp2);
- EXPECT_EQ(dchecks_are_fatal ? 1 : 0, g_log_sink_call_count);
- DCHECK_EQ(mp2, &MemberFunctions::MemberFunction1);
- EXPECT_EQ(dchecks_are_fatal ? 2 : 0, g_log_sink_call_count);
-}
-
-TEST_F(LoggingTest, DcheckReleaseBehavior) {
- int some_variable = 1;
- // These should still reference |some_variable| so we don't get
- // unused variable warnings.
- DCHECK(some_variable) << "test";
- DPCHECK(some_variable) << "test";
- DCHECK_EQ(some_variable, 1) << "test";
-}
-
-TEST_F(LoggingTest, DCheckEqStatements) {
- bool reached = false;
- if (false)
- DCHECK_EQ(false, true); // Unreached.
- else
- DCHECK_EQ(true, reached = true); // Reached, passed.
- ASSERT_EQ(DCHECK_IS_ON() ? true : false, reached);
-
- if (false)
- DCHECK_EQ(false, true); // Unreached.
-}
-
-TEST_F(LoggingTest, CheckEqStatements) {
- bool reached = false;
- if (false)
- CHECK_EQ(false, true); // Unreached.
- else
- CHECK_EQ(true, reached = true); // Reached, passed.
- ASSERT_TRUE(reached);
-
- if (false)
- CHECK_EQ(false, true); // Unreached.
-}
-
-TEST_F(LoggingTest, NestedLogAssertHandlers) {
- ::testing::InSequence dummy;
- ::testing::StrictMock<MockLogAssertHandler> handler_a, handler_b;
-
- EXPECT_CALL(
- handler_a,
- HandleLogAssert(
- _, _, base::StringPiece("First assert must be caught by handler_a"),
- _));
- EXPECT_CALL(
- handler_b,
- HandleLogAssert(
- _, _, base::StringPiece("Second assert must be caught by handler_b"),
- _));
- EXPECT_CALL(
- handler_a,
- HandleLogAssert(
- _, _,
- base::StringPiece("Last assert must be caught by handler_a again"),
- _));
-
- logging::ScopedLogAssertHandler scoped_handler_a(base::Bind(
- &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler_a)));
-
- // Using LOG(FATAL) rather than CHECK(false) here since log messages aren't
- // preserved for CHECKs in official builds.
- LOG(FATAL) << "First assert must be caught by handler_a";
-
- {
- logging::ScopedLogAssertHandler scoped_handler_b(base::Bind(
- &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler_b)));
- LOG(FATAL) << "Second assert must be caught by handler_b";
- }
-
- LOG(FATAL) << "Last assert must be caught by handler_a again";
-}
-
-// Test that defining an operator<< for a type in a namespace doesn't prevent
-// other code in that namespace from calling the operator<<(ostream, wstring)
-// defined by logging.h. This can fail if operator<<(ostream, wstring) can't be
-// found by ADL, since defining another operator<< prevents name lookup from
-// looking in the global namespace.
-namespace nested_test {
- class Streamable {};
- ALLOW_UNUSED_TYPE std::ostream& operator<<(std::ostream& out,
- const Streamable&) {
- return out << "Streamable";
- }
- TEST_F(LoggingTest, StreamingWstringFindsCorrectOperator) {
- std::wstring wstr = L"Hello World";
- std::ostringstream ostr;
- ostr << wstr;
- EXPECT_EQ("Hello World", ostr.str());
- }
-} // namespace nested_test
-
-#if DCHECK_IS_CONFIGURABLE
-TEST_F(LoggingTest, ConfigurableDCheck) {
- // Verify that DCHECKs default to non-fatal in configurable-DCHECK builds.
- // Note that we require only that DCHECK is non-fatal by default, rather
- // than requiring that it be exactly INFO, ERROR, etc level.
- EXPECT_LT(LOG_DCHECK, LOG_FATAL);
- DCHECK(false);
-
- // Verify that DCHECK* aren't hard-wired to crash on failure.
- LOG_DCHECK = LOG_INFO;
- DCHECK(false);
- DCHECK_EQ(1, 2);
-
- // Verify that DCHECK does crash if LOG_DCHECK is set to LOG_FATAL.
- LOG_DCHECK = LOG_FATAL;
-
- ::testing::StrictMock<MockLogAssertHandler> handler;
- EXPECT_CALL(handler, HandleLogAssert(_, _, _, _)).Times(2);
- {
- logging::ScopedLogAssertHandler scoped_handler_b(base::Bind(
- &MockLogAssertHandler::HandleLogAssert, base::Unretained(&handler)));
- DCHECK(false);
- DCHECK_EQ(1, 2);
- }
-}
-
-TEST_F(LoggingTest, ConfigurableDCheckFeature) {
- // Initialize FeatureList with and without DcheckIsFatal, and verify the
- // value of LOG_DCHECK. Note that we don't require that DCHECK take a
- // specific value when the feature is off, only that it is non-fatal.
-
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitFromCommandLine("DcheckIsFatal", "");
- EXPECT_EQ(LOG_DCHECK, LOG_FATAL);
- }
-
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitFromCommandLine("", "DcheckIsFatal");
- EXPECT_LT(LOG_DCHECK, LOG_FATAL);
- }
-
- // The default case is last, so we leave LOG_DCHECK in the default state.
- {
- base::test::ScopedFeatureList feature_list;
- feature_list.InitFromCommandLine("", "");
- EXPECT_LT(LOG_DCHECK, LOG_FATAL);
- }
-}
-#endif // DCHECK_IS_CONFIGURABLE
-
-#if defined(OS_FUCHSIA)
-TEST_F(LoggingTest, FuchsiaLogging) {
- MockLogSource mock_log_source;
- EXPECT_CALL(mock_log_source, Log())
- .Times(DCHECK_IS_ON() ? 2 : 1)
- .WillRepeatedly(Return("log message"));
-
- SetMinLogLevel(LOG_INFO);
-
- EXPECT_TRUE(LOG_IS_ON(INFO));
- EXPECT_TRUE((DCHECK_IS_ON() != 0) == DLOG_IS_ON(INFO));
-
- ZX_LOG(INFO, ZX_ERR_INTERNAL) << mock_log_source.Log();
- ZX_DLOG(INFO, ZX_ERR_INTERNAL) << mock_log_source.Log();
-
- ZX_CHECK(true, ZX_ERR_INTERNAL);
- ZX_DCHECK(true, ZX_ERR_INTERNAL);
-}
-#endif // defined(OS_FUCHSIA)
-
-} // namespace
-
-} // namespace logging
diff --git a/base/mac/dispatch_source_mach_unittest.cc b/base/mac/dispatch_source_mach_unittest.cc
deleted file mode 100644
index 738a137..0000000
--- a/base/mac/dispatch_source_mach_unittest.cc
+++ /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.
-
-#include "base/mac/dispatch_source_mach.h"
-
-#include <mach/mach.h>
-
-#include <memory>
-
-#include "base/logging.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/test/test_timeouts.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class DispatchSourceMachTest : public testing::Test {
- public:
- void SetUp() override {
- mach_port_t port = MACH_PORT_NULL;
- ASSERT_EQ(KERN_SUCCESS, mach_port_allocate(mach_task_self(),
- MACH_PORT_RIGHT_RECEIVE, &port));
- receive_right_.reset(port);
-
- ASSERT_EQ(KERN_SUCCESS, mach_port_insert_right(mach_task_self(), port,
- port, MACH_MSG_TYPE_MAKE_SEND));
- send_right_.reset(port);
- }
-
- mach_port_t GetPort() { return receive_right_.get(); }
-
- void WaitForSemaphore(dispatch_semaphore_t semaphore) {
- dispatch_semaphore_wait(semaphore, dispatch_time(
- DISPATCH_TIME_NOW,
- TestTimeouts::action_timeout().InSeconds() * NSEC_PER_SEC));
- }
-
- private:
- base::mac::ScopedMachReceiveRight receive_right_;
- base::mac::ScopedMachSendRight send_right_;
-};
-
-TEST_F(DispatchSourceMachTest, ReceiveAfterResume) {
- dispatch_semaphore_t signal = dispatch_semaphore_create(0);
- mach_port_t port = GetPort();
-
- bool __block did_receive = false;
- DispatchSourceMach source("org.chromium.base.test.ReceiveAfterResume",
- port, ^{
- mach_msg_empty_rcv_t msg = {{0}};
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_local_port = port;
- mach_msg_receive(&msg.header);
- did_receive = true;
-
- dispatch_semaphore_signal(signal);
- });
-
- mach_msg_empty_send_t msg = {{0}};
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_remote_port = port;
- msg.header.msgh_bits = MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND);
- ASSERT_EQ(KERN_SUCCESS, mach_msg_send(&msg.header));
-
- EXPECT_FALSE(did_receive);
-
- source.Resume();
-
- WaitForSemaphore(signal);
- dispatch_release(signal);
-
- EXPECT_TRUE(did_receive);
-}
-
-TEST_F(DispatchSourceMachTest, NoMessagesAfterDestruction) {
- mach_port_t port = GetPort();
-
- std::unique_ptr<int> count(new int(0));
- int* __block count_ptr = count.get();
-
- std::unique_ptr<DispatchSourceMach> source(new DispatchSourceMach(
- "org.chromium.base.test.NoMessagesAfterDestruction", port, ^{
- mach_msg_empty_rcv_t msg = {{0}};
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_local_port = port;
- mach_msg_receive(&msg.header);
- LOG(INFO) << "Receieve " << *count_ptr;
- ++(*count_ptr);
- }));
- source->Resume();
-
- dispatch_queue_t queue =
- dispatch_queue_create("org.chromium.base.test.MessageSend", NULL);
- dispatch_semaphore_t signal = dispatch_semaphore_create(0);
- for (int i = 0; i < 30; ++i) {
- dispatch_async(queue, ^{
- mach_msg_empty_send_t msg = {{0}};
- msg.header.msgh_size = sizeof(msg);
- msg.header.msgh_remote_port = port;
- msg.header.msgh_bits =
- MACH_MSGH_BITS_REMOTE(MACH_MSG_TYPE_COPY_SEND);
- mach_msg_send(&msg.header);
- });
-
- // After sending five messages, shut down the source and taint the
- // pointer the handler dereferences. The test will crash if |count_ptr|
- // is being used after "free".
- if (i == 5) {
- std::unique_ptr<DispatchSourceMach>* source_ptr = &source;
- dispatch_async(queue, ^{
- source_ptr->reset();
- count_ptr = reinterpret_cast<int*>(0xdeaddead);
- dispatch_semaphore_signal(signal);
- });
- }
- }
-
- WaitForSemaphore(signal);
- dispatch_release(signal);
-
- dispatch_release(queue);
-}
-
-} // namespace base
diff --git a/base/mac/mach_port_broker_unittest.cc b/base/mac/mach_port_broker_unittest.cc
deleted file mode 100644
index bff8eb6..0000000
--- a/base/mac/mach_port_broker_unittest.cc
+++ /dev/null
@@ -1,133 +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/mac/mach_port_broker.h"
-
-#include "base/command_line.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-
-namespace {
-const char kBootstrapPortName[] = "thisisatest";
-}
-
-class MachPortBrokerTest : public testing::Test,
- public base::PortProvider::Observer {
- public:
- MachPortBrokerTest()
- : broker_(kBootstrapPortName),
- event_(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED),
- received_process_(kNullProcessHandle) {
- broker_.AddObserver(this);
- }
- ~MachPortBrokerTest() override {
- broker_.RemoveObserver(this);
- }
-
- // Helper function to acquire/release locks and call |PlaceholderForPid()|.
- void AddPlaceholderForPid(base::ProcessHandle pid) {
- base::AutoLock lock(broker_.GetLock());
- broker_.AddPlaceholderForPid(pid);
- }
-
- // Helper function to acquire/release locks and call |FinalizePid()|.
- void FinalizePid(base::ProcessHandle pid,
- mach_port_t task_port) {
- base::AutoLock lock(broker_.GetLock());
- broker_.FinalizePid(pid, task_port);
- }
-
- void WaitForTaskPort() {
- event_.Wait();
- }
-
- // base::PortProvider::Observer:
- void OnReceivedTaskPort(ProcessHandle process) override {
- received_process_ = process;
- event_.Signal();
- }
-
- protected:
- MachPortBroker broker_;
- WaitableEvent event_;
- ProcessHandle received_process_;
-};
-
-TEST_F(MachPortBrokerTest, Locks) {
- // Acquire and release the locks. Nothing bad should happen.
- base::AutoLock lock(broker_.GetLock());
-}
-
-TEST_F(MachPortBrokerTest, AddPlaceholderAndFinalize) {
- // Add a placeholder for PID 1.
- AddPlaceholderForPid(1);
- EXPECT_EQ(0u, broker_.TaskForPid(1));
-
- // Finalize PID 1.
- FinalizePid(1, 100u);
- EXPECT_EQ(100u, broker_.TaskForPid(1));
-
- // Should be no entry for PID 2.
- EXPECT_EQ(0u, broker_.TaskForPid(2));
-}
-
-TEST_F(MachPortBrokerTest, FinalizeUnknownPid) {
- // Finalizing an entry for an unknown pid should not add it to the map.
- FinalizePid(1u, 100u);
- EXPECT_EQ(0u, broker_.TaskForPid(1u));
-}
-
-MULTIPROCESS_TEST_MAIN(MachPortBrokerTestChild) {
- CHECK(base::MachPortBroker::ChildSendTaskPortToParent(kBootstrapPortName));
- return 0;
-}
-
-TEST_F(MachPortBrokerTest, ReceivePortFromChild) {
- ASSERT_TRUE(broker_.Init());
- CommandLine command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
- broker_.GetLock().Acquire();
- base::Process test_child_process = base::SpawnMultiProcessTestChild(
- "MachPortBrokerTestChild", command_line, LaunchOptions());
- broker_.AddPlaceholderForPid(test_child_process.Handle());
- broker_.GetLock().Release();
-
- WaitForTaskPort();
- EXPECT_EQ(test_child_process.Handle(), received_process_);
-
- int rv = -1;
- ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
- TestTimeouts::action_timeout(), &rv));
- EXPECT_EQ(0, rv);
-
- EXPECT_NE(static_cast<mach_port_t>(MACH_PORT_NULL),
- broker_.TaskForPid(test_child_process.Handle()));
-}
-
-TEST_F(MachPortBrokerTest, ReceivePortFromChildWithoutAdding) {
- ASSERT_TRUE(broker_.Init());
- CommandLine command_line(
- base::GetMultiProcessTestChildBaseCommandLine());
- broker_.GetLock().Acquire();
- base::Process test_child_process = base::SpawnMultiProcessTestChild(
- "MachPortBrokerTestChild", command_line, LaunchOptions());
- broker_.GetLock().Release();
-
- int rv = -1;
- ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
- TestTimeouts::action_timeout(), &rv));
- EXPECT_EQ(0, rv);
-
- EXPECT_EQ(static_cast<mach_port_t>(MACH_PORT_NULL),
- broker_.TaskForPid(test_child_process.Handle()));
-}
-
-} // namespace base
diff --git a/base/md5_unittest.cc b/base/md5_unittest.cc
deleted file mode 100644
index b27efe9..0000000
--- a/base/md5_unittest.cc
+++ /dev/null
@@ -1,253 +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/md5.h"
-
-#include <string.h>
-
-#include <memory>
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(MD5, DigestToBase16) {
- MD5Digest digest;
-
- int data[] = {
- 0xd4, 0x1d, 0x8c, 0xd9,
- 0x8f, 0x00, 0xb2, 0x04,
- 0xe9, 0x80, 0x09, 0x98,
- 0xec, 0xf8, 0x42, 0x7e
- };
-
- for (int i = 0; i < 16; ++i)
- digest.a[i] = data[i] & 0xff;
-
- std::string actual = MD5DigestToBase16(digest);
- std::string expected = "d41d8cd98f00b204e9800998ecf8427e";
-
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5SumEmtpyData) {
- MD5Digest digest;
- const char data[] = "";
-
- MD5Sum(data, strlen(data), &digest);
-
- int expected[] = {
- 0xd4, 0x1d, 0x8c, 0xd9,
- 0x8f, 0x00, 0xb2, 0x04,
- 0xe9, 0x80, 0x09, 0x98,
- 0xec, 0xf8, 0x42, 0x7e
- };
-
- for (int i = 0; i < 16; ++i)
- EXPECT_EQ(expected[i], digest.a[i] & 0xFF);
-}
-
-TEST(MD5, MD5SumOneByteData) {
- MD5Digest digest;
- const char data[] = "a";
-
- MD5Sum(data, strlen(data), &digest);
-
- int expected[] = {
- 0x0c, 0xc1, 0x75, 0xb9,
- 0xc0, 0xf1, 0xb6, 0xa8,
- 0x31, 0xc3, 0x99, 0xe2,
- 0x69, 0x77, 0x26, 0x61
- };
-
- for (int i = 0; i < 16; ++i)
- EXPECT_EQ(expected[i], digest.a[i] & 0xFF);
-}
-
-TEST(MD5, MD5SumLongData) {
- const int length = 10 * 1024 * 1024 + 1;
- std::unique_ptr<char[]> data(new char[length]);
-
- for (int i = 0; i < length; ++i)
- data[i] = i & 0xFF;
-
- MD5Digest digest;
- MD5Sum(data.get(), length, &digest);
-
- int expected[] = {
- 0x90, 0xbd, 0x6a, 0xd9,
- 0x0a, 0xce, 0xf5, 0xad,
- 0xaa, 0x92, 0x20, 0x3e,
- 0x21, 0xc7, 0xa1, 0x3e
- };
-
- for (int i = 0; i < 16; ++i)
- EXPECT_EQ(expected[i], digest.a[i] & 0xFF);
-}
-
-TEST(MD5, ContextWithEmptyData) {
- MD5Context ctx;
- MD5Init(&ctx);
-
- MD5Digest digest;
- MD5Final(&digest, &ctx);
-
- int expected[] = {
- 0xd4, 0x1d, 0x8c, 0xd9,
- 0x8f, 0x00, 0xb2, 0x04,
- 0xe9, 0x80, 0x09, 0x98,
- 0xec, 0xf8, 0x42, 0x7e
- };
-
- for (int i = 0; i < 16; ++i)
- EXPECT_EQ(expected[i], digest.a[i] & 0xFF);
-}
-
-TEST(MD5, ContextWithLongData) {
- MD5Context ctx;
- MD5Init(&ctx);
-
- const int length = 10 * 1024 * 1024 + 1;
- std::unique_ptr<char[]> data(new char[length]);
-
- for (int i = 0; i < length; ++i)
- data[i] = i & 0xFF;
-
- int total = 0;
- while (total < length) {
- int len = 4097; // intentionally not 2^k.
- if (len > length - total)
- len = length - total;
-
- MD5Update(&ctx,
- StringPiece(reinterpret_cast<char*>(data.get() + total), len));
- total += len;
- }
-
- EXPECT_EQ(length, total);
-
- MD5Digest digest;
- MD5Final(&digest, &ctx);
-
- int expected[] = {
- 0x90, 0xbd, 0x6a, 0xd9,
- 0x0a, 0xce, 0xf5, 0xad,
- 0xaa, 0x92, 0x20, 0x3e,
- 0x21, 0xc7, 0xa1, 0x3e
- };
-
- for (int i = 0; i < 16; ++i)
- EXPECT_EQ(expected[i], digest.a[i] & 0xFF);
-}
-
-// Example data from http://www.ietf.org/rfc/rfc1321.txt A.5 Test Suite
-TEST(MD5, MD5StringTestSuite1) {
- std::string actual = MD5String("");
- std::string expected = "d41d8cd98f00b204e9800998ecf8427e";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5StringTestSuite2) {
- std::string actual = MD5String("a");
- std::string expected = "0cc175b9c0f1b6a831c399e269772661";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5StringTestSuite3) {
- std::string actual = MD5String("abc");
- std::string expected = "900150983cd24fb0d6963f7d28e17f72";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5StringTestSuite4) {
- std::string actual = MD5String("message digest");
- std::string expected = "f96b697d7cb7938d525a2f31aaf161d0";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5StringTestSuite5) {
- std::string actual = MD5String("abcdefghijklmnopqrstuvwxyz");
- std::string expected = "c3fcd3d76192e4007dfb496cca67e13b";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5StringTestSuite6) {
- std::string actual = MD5String("ABCDEFGHIJKLMNOPQRSTUVWXYZ"
- "abcdefghijklmnopqrstuvwxyz"
- "0123456789");
- std::string expected = "d174ab98d277d9f5a5611c2c9f419d9f";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, MD5StringTestSuite7) {
- std::string actual = MD5String("12345678901234567890"
- "12345678901234567890"
- "12345678901234567890"
- "12345678901234567890");
- std::string expected = "57edf4a22be3c955ac49da2e2107b67a";
- EXPECT_EQ(expected, actual);
-}
-
-TEST(MD5, ContextWithStringData) {
- MD5Context ctx;
- MD5Init(&ctx);
-
- MD5Update(&ctx, "abc");
-
- MD5Digest digest;
- MD5Final(&digest, &ctx);
-
- std::string actual = MD5DigestToBase16(digest);
- std::string expected = "900150983cd24fb0d6963f7d28e17f72";
-
- EXPECT_EQ(expected, actual);
-}
-
-// Test that a digest generated by MD5IntermediateFinal() gives the same results
-// as an independently-calculated digest, and also does not modify the context.
-TEST(MD5, IntermediateFinal) {
- // Independent context over the header.
- MD5Context check_header_context;
- MD5Init(&check_header_context);
-
- // Independent context over entire input.
- MD5Context check_full_context;
- MD5Init(&check_full_context);
-
- // Context intermediate digest will be calculated from.
- MD5Context context;
- MD5Init(&context);
-
- static const char kHeader[] = "header data";
- static const char kBody[] = "payload data";
-
- MD5Update(&context, kHeader);
- MD5Update(&check_header_context, kHeader);
- MD5Update(&check_full_context, kHeader);
-
- MD5Digest check_header_digest;
- MD5Final(&check_header_digest, &check_header_context);
-
- MD5Digest header_digest;
- MD5IntermediateFinal(&header_digest, &context);
-
- MD5Update(&context, kBody);
- MD5Update(&check_full_context, kBody);
-
- MD5Digest check_full_digest;
- MD5Final(&check_full_digest, &check_full_context);
-
- MD5Digest digest;
- MD5Final(&digest, &context);
-
- // The header and full digest pairs are the same, and they aren't the same as
- // each other.
- EXPECT_TRUE(!memcmp(&header_digest, &check_header_digest,
- sizeof(header_digest)));
- EXPECT_TRUE(!memcmp(&digest, &check_full_digest, sizeof(digest)));
- EXPECT_TRUE(memcmp(&digest, &header_digest, sizeof(digest)));
-}
-
-} // namespace base
diff --git a/base/memory/aligned_memory_unittest.cc b/base/memory/aligned_memory_unittest.cc
deleted file mode 100644
index 29ed706..0000000
--- a/base/memory/aligned_memory_unittest.cc
+++ /dev/null
@@ -1,46 +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/memory/aligned_memory.h"
-
-#include <memory>
-
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#define EXPECT_ALIGNED(ptr, align) \
- EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
-
-namespace base {
-
-TEST(AlignedMemoryTest, DynamicAllocation) {
- void* p = AlignedAlloc(8, 8);
- EXPECT_TRUE(p);
- EXPECT_ALIGNED(p, 8);
- AlignedFree(p);
-
- p = AlignedAlloc(8, 16);
- EXPECT_TRUE(p);
- EXPECT_ALIGNED(p, 16);
- AlignedFree(p);
-
- p = AlignedAlloc(8, 256);
- EXPECT_TRUE(p);
- EXPECT_ALIGNED(p, 256);
- AlignedFree(p);
-
- p = AlignedAlloc(8, 4096);
- EXPECT_TRUE(p);
- EXPECT_ALIGNED(p, 4096);
- AlignedFree(p);
-}
-
-TEST(AlignedMemoryTest, ScopedDynamicAllocation) {
- std::unique_ptr<float, AlignedFreeDeleter> p(
- static_cast<float*>(AlignedAlloc(8, 8)));
- EXPECT_TRUE(p.get());
- EXPECT_ALIGNED(p.get(), 8);
-}
-
-} // namespace base
diff --git a/base/memory/discardable_shared_memory_unittest.cc b/base/memory/discardable_shared_memory_unittest.cc
deleted file mode 100644
index bda37f6..0000000
--- 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_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(nullptr, 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/linked_ptr_unittest.cc b/base/memory/linked_ptr_unittest.cc
deleted file mode 100644
index 344ffa4..0000000
--- a/base/memory/linked_ptr_unittest.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 <string>
-
-#include "base/memory/linked_ptr.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-int num = 0;
-
-std::string history;
-
-// Class which tracks allocation/deallocation
-struct A {
- A(): mynum(num++) { history += base::StringPrintf("A%d ctor\n", mynum); }
- virtual ~A() { history += base::StringPrintf("A%d dtor\n", mynum); }
- virtual void Use() { history += base::StringPrintf("A%d use\n", mynum); }
- int mynum;
-};
-
-// Subclass
-struct B: public A {
- B() { history += base::StringPrintf("B%d ctor\n", mynum); }
- ~B() override { history += base::StringPrintf("B%d dtor\n", mynum); }
- void Use() override { history += base::StringPrintf("B%d use\n", mynum); }
-};
-
-} // namespace
-
-TEST(LinkedPtrTest, Test) {
- {
- linked_ptr<A> a0, a1, a2;
- a0 = *&a0; // The *& defeats Clang's -Wself-assign warning.
- a1 = a2;
- ASSERT_EQ(a0.get(), static_cast<A*>(nullptr));
- ASSERT_EQ(a1.get(), static_cast<A*>(nullptr));
- ASSERT_EQ(a2.get(), static_cast<A*>(nullptr));
- ASSERT_TRUE(a0 == nullptr);
- ASSERT_TRUE(a1 == nullptr);
- ASSERT_TRUE(a2 == nullptr);
-
- {
- linked_ptr<A> a3(new A);
- a0 = a3;
- ASSERT_TRUE(a0 == a3);
- ASSERT_TRUE(a0 != nullptr);
- ASSERT_TRUE(a0.get() == a3);
- ASSERT_TRUE(a0 == a3.get());
- linked_ptr<A> a4(a0);
- a1 = a4;
- linked_ptr<A> a5(new A);
- ASSERT_TRUE(a5.get() != a3);
- ASSERT_TRUE(a5 != a3.get());
- a2 = a5;
- linked_ptr<B> b0(new B);
- linked_ptr<A> a6(b0);
- ASSERT_TRUE(b0 == a6);
- ASSERT_TRUE(a6 == b0);
- ASSERT_TRUE(b0 != nullptr);
- a5 = b0;
- a5 = b0;
- a3->Use();
- a4->Use();
- a5->Use();
- a6->Use();
- b0->Use();
- (*b0).Use();
- b0.get()->Use();
- }
-
- a0->Use();
- a1->Use();
- a2->Use();
-
- a1 = a2;
- a2.reset(new A);
- a0.reset();
-
- linked_ptr<A> a7;
- }
-
- ASSERT_EQ(history,
- "A0 ctor\n"
- "A1 ctor\n"
- "A2 ctor\n"
- "B2 ctor\n"
- "A0 use\n"
- "A0 use\n"
- "B2 use\n"
- "B2 use\n"
- "B2 use\n"
- "B2 use\n"
- "B2 use\n"
- "B2 dtor\n"
- "A2 dtor\n"
- "A0 use\n"
- "A0 use\n"
- "A1 use\n"
- "A3 ctor\n"
- "A0 dtor\n"
- "A3 dtor\n"
- "A1 dtor\n"
- );
-}
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 37ed767..0000000
--- 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_pressure_listener_unittest.cc b/base/memory/memory_pressure_listener_unittest.cc
deleted file mode 100644
index 87d5f4c..0000000
--- 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_chromeos_unittest.cc b/base/memory/memory_pressure_monitor_chromeos_unittest.cc
deleted file mode 100644
index ee00091..0000000
--- 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_mac_unittest.cc b/base/memory/memory_pressure_monitor_mac_unittest.cc
deleted file mode 100644
index ff464fb..0000000
--- a/base/memory/memory_pressure_monitor_mac_unittest.cc
+++ /dev/null
@@ -1,228 +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_mac.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/mac/scoped_cftyperef.h"
-#include "base/macros.h"
-#include "base/test/histogram_tester.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace mac {
-
-class TestMemoryPressureMonitor : public MemoryPressureMonitor {
- public:
- using MemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel;
-
- // A HistogramTester for verifying correct UMA stat generation.
- base::HistogramTester tester;
-
- TestMemoryPressureMonitor() { }
-
- // Clears the next run loop update time so that the next pass of the run
- // loop checks the memory pressure level immediately. Normally there's a
- // 5 second delay between pressure readings.
- void ResetRunLoopUpdateTime() { next_run_loop_update_time_ = 0; }
-
- // Sets the last UMA stat report time. Time spent in memory pressure is
- // recorded in 5-second "ticks" from the last time statistics were recorded.
- void SetLastStatisticReportTime(CFTimeInterval time) {
- last_statistic_report_time_ = time;
- }
-
- // Sets the raw macOS memory pressure level read by the memory pressure
- // monitor.
- int macos_pressure_level_for_testing_;
-
- // Exposes the UpdatePressureLevel() method for testing.
- void UpdatePressureLevel() { MemoryPressureMonitor::UpdatePressureLevel(); }
-
- // Returns the number of seconds left over from the last UMA tick
- // calculation.
- int SubTickSeconds() { return subtick_seconds_; }
-
- // Returns the number of seconds per UMA tick.
- static int GetSecondsPerUMATick() {
- return MemoryPressureMonitor::GetSecondsPerUMATick();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
-
- int GetMacMemoryPressureLevel() override {
- return macos_pressure_level_for_testing_;
- }
-};
-
-TEST(MacMemoryPressureMonitorTest, MemoryPressureFromMacMemoryPressure) {
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- DISPATCH_MEMORYPRESSURE_NORMAL));
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- DISPATCH_MEMORYPRESSURE_WARN));
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- DISPATCH_MEMORYPRESSURE_CRITICAL));
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- 0));
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- 3));
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- 5));
- EXPECT_EQ(
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- TestMemoryPressureMonitor::MemoryPressureLevelForMacMemoryPressureLevel(
- -1));
-}
-
-TEST(MacMemoryPressureMonitorTest, CurrentMemoryPressure) {
- TestMemoryPressureMonitor monitor;
-
- MemoryPressureListener::MemoryPressureLevel memory_pressure =
- monitor.GetCurrentPressureLevel();
- EXPECT_TRUE(memory_pressure ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE ||
- memory_pressure ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE ||
- memory_pressure ==
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
-}
-
-TEST(MacMemoryPressureMonitorTest, MemoryPressureConversion) {
- TestMemoryPressureMonitor monitor;
-
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_NORMAL;
- monitor.UpdatePressureLevel();
- MemoryPressureListener::MemoryPressureLevel memory_pressure =
- monitor.GetCurrentPressureLevel();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- memory_pressure);
-
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_WARN;
- monitor.UpdatePressureLevel();
- memory_pressure = monitor.GetCurrentPressureLevel();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- memory_pressure);
-
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_CRITICAL;
- monitor.UpdatePressureLevel();
- memory_pressure = monitor.GetCurrentPressureLevel();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- memory_pressure);
-}
-
-TEST(MacMemoryPressureMonitorTest, MemoryPressureRunLoopChecking) {
- TestMemoryPressureMonitor monitor;
-
- // To test grabbing the memory presure at the end of the run loop, we have to
- // run the run loop, but to do that the run loop needs a run loop source. Add
- // a timer as the source. We know that the exit observer is attached to
- // the kMessageLoopExclusiveRunLoopMode mode, so use that mode.
- ScopedCFTypeRef<CFRunLoopTimerRef> timer_ref(CFRunLoopTimerCreate(
- NULL, CFAbsoluteTimeGetCurrent() + 10, 0, 0, 0, nullptr, nullptr));
- CFRunLoopAddTimer(CFRunLoopGetCurrent(), timer_ref,
- kMessageLoopExclusiveRunLoopMode);
-
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_WARN;
- monitor.ResetRunLoopUpdateTime();
- CFRunLoopRunInMode(kMessageLoopExclusiveRunLoopMode, 0, true);
- EXPECT_EQ(monitor.GetCurrentPressureLevel(),
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE);
-
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_CRITICAL;
- monitor.ResetRunLoopUpdateTime();
- CFRunLoopRunInMode(kMessageLoopExclusiveRunLoopMode, 0, true);
- EXPECT_EQ(monitor.GetCurrentPressureLevel(),
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL);
-
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_NORMAL;
- monitor.ResetRunLoopUpdateTime();
- CFRunLoopRunInMode(kMessageLoopExclusiveRunLoopMode, 0, true);
- EXPECT_EQ(monitor.GetCurrentPressureLevel(),
- MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE);
-
- CFRunLoopRemoveTimer(CFRunLoopGetCurrent(), timer_ref,
- kMessageLoopExclusiveRunLoopMode);
-}
-
-TEST(MacMemoryPressureMonitorTest, RecordMemoryPressureStats) {
- TestMemoryPressureMonitor monitor;
- const char* kHistogram = "Memory.PressureLevel";
- CFTimeInterval now = CFAbsoluteTimeGetCurrent();
- const int seconds_per_tick =
- TestMemoryPressureMonitor::GetSecondsPerUMATick();
-
- // Set the initial pressure level.
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_NORMAL;
- // Incur one UMA tick of time (and include one extra second of elapsed time).
- monitor.SetLastStatisticReportTime(now - (seconds_per_tick + 1));
- monitor.UpdatePressureLevel();
- monitor.tester.ExpectTotalCount(kHistogram, 1);
- monitor.tester.ExpectBucketCount(kHistogram, 0, 1);
- // The report time above included an extra second so there should be 1
- // sub-tick second left over.
- EXPECT_EQ(1, monitor.SubTickSeconds());
-
- // Simulate sitting in normal pressure for 1 second less than 6 UMA tick
- // seconds and then elevating to warning. With the left over sub-tick second
- // from above, the total elapsed ticks should be an even 6 UMA ticks.
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_WARN;
- monitor.SetLastStatisticReportTime(now - (seconds_per_tick * 6 - 1));
- monitor.UpdatePressureLevel();
- monitor.tester.ExpectTotalCount(kHistogram, 7);
- monitor.tester.ExpectBucketCount(kHistogram, 0, 7);
- monitor.tester.ExpectBucketCount(kHistogram, 1, 0);
- EXPECT_EQ(0, monitor.SubTickSeconds());
-
- // Simulate sitting in warning pressure for 20 UMA ticks and 2 seconds, and
- // then elevating to critical.
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_CRITICAL;
- monitor.SetLastStatisticReportTime(now - (20 * seconds_per_tick + 2));
- monitor.UpdatePressureLevel();
- monitor.tester.ExpectTotalCount(kHistogram, 27);
- monitor.tester.ExpectBucketCount(kHistogram, 0, 7);
- monitor.tester.ExpectBucketCount(kHistogram, 1, 20);
- monitor.tester.ExpectBucketCount(kHistogram, 2, 0);
- EXPECT_EQ(2, monitor.SubTickSeconds());
-
- // A quick update while critical - the stats should not budge because less
- // than 1 tick of time has elapsed.
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_CRITICAL;
- monitor.SetLastStatisticReportTime(now - 1);
- monitor.UpdatePressureLevel();
- monitor.tester.ExpectTotalCount(kHistogram, 27);
- monitor.tester.ExpectBucketCount(kHistogram, 0, 7);
- monitor.tester.ExpectBucketCount(kHistogram, 1, 20);
- monitor.tester.ExpectBucketCount(kHistogram, 2, 0);
- EXPECT_EQ(3, monitor.SubTickSeconds());
-
- // A quick change back to normal. Less than 1 tick of time has elapsed, but
- // in this case the pressure level changed, so the critical bucket should
- // get another sample (otherwise we could miss quick level changes).
- monitor.macos_pressure_level_for_testing_ = DISPATCH_MEMORYPRESSURE_NORMAL;
- monitor.SetLastStatisticReportTime(now - 1);
- monitor.UpdatePressureLevel();
- monitor.tester.ExpectTotalCount(kHistogram, 28);
- monitor.tester.ExpectBucketCount(kHistogram, 0, 7);
- monitor.tester.ExpectBucketCount(kHistogram, 1, 20);
- monitor.tester.ExpectBucketCount(kHistogram, 2, 1);
- // When less than 1 tick of time has elapsed but the pressure level changed,
- // the subtick remainder gets zeroed out.
- EXPECT_EQ(0, monitor.SubTickSeconds());
-}
-} // namespace mac
-} // 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 e974741..0000000
--- 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/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/memory_pressure_monitor_win_unittest.cc b/base/memory/memory_pressure_monitor_win_unittest.cc
deleted file mode 100644
index 1002a01..0000000
--- a/base/memory/memory_pressure_monitor_win_unittest.cc
+++ /dev/null
@@ -1,299 +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_win.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 "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-struct PressureSettings {
- int phys_left_mb;
- MemoryPressureListener::MemoryPressureLevel level;
-};
-
-} // namespace
-
-// This is outside of the anonymous namespace so that it can be seen as a friend
-// to the monitor class.
-class TestMemoryPressureMonitor : public MemoryPressureMonitor {
- public:
- using MemoryPressureMonitor::CalculateCurrentPressureLevel;
- using MemoryPressureMonitor::CheckMemoryPressure;
-
- static const DWORDLONG kMBBytes = 1024 * 1024;
-
- explicit TestMemoryPressureMonitor(bool large_memory)
- : mem_status_() {
- // Generate a plausible amount of memory.
- mem_status_.ullTotalPhys =
- static_cast<DWORDLONG>(GenerateTotalMemoryMb(large_memory)) * kMBBytes;
-
- // Rerun InferThresholds using the test fixture's GetSystemMemoryStatus.
- InferThresholds();
- // Stop the timer.
- StopObserving();
- }
-
- TestMemoryPressureMonitor(int system_memory_mb,
- int moderate_threshold_mb,
- int critical_threshold_mb)
- : MemoryPressureMonitor(moderate_threshold_mb, critical_threshold_mb),
- mem_status_() {
- // Set the amount of system memory.
- mem_status_.ullTotalPhys = static_cast<DWORDLONG>(
- system_memory_mb * kMBBytes);
-
- // Stop the timer.
- StopObserving();
- }
-
- virtual ~TestMemoryPressureMonitor() {}
-
- MOCK_METHOD1(OnMemoryPressure,
- void(MemoryPressureListener::MemoryPressureLevel level));
-
- // Generates an amount of total memory that is consistent with the requested
- // memory model.
- int GenerateTotalMemoryMb(bool large_memory) {
- int total_mb = 64;
- while (total_mb < MemoryPressureMonitor::kLargeMemoryThresholdMb)
- total_mb *= 2;
- if (large_memory)
- return total_mb * 2;
- return total_mb / 2;
- }
-
- // Sets up the memory status to reflect the provided absolute memory left.
- void SetMemoryFree(int phys_left_mb) {
- // ullTotalPhys is set in the constructor and not modified.
-
- // Set the amount of available memory.
- mem_status_.ullAvailPhys =
- static_cast<DWORDLONG>(phys_left_mb) * kMBBytes;
- DCHECK_LT(mem_status_.ullAvailPhys, mem_status_.ullTotalPhys);
-
- // These fields are unused.
- mem_status_.dwMemoryLoad = 0;
- mem_status_.ullTotalPageFile = 0;
- mem_status_.ullAvailPageFile = 0;
- mem_status_.ullTotalVirtual = 0;
- mem_status_.ullAvailVirtual = 0;
- }
-
- void SetNone() {
- SetMemoryFree(moderate_threshold_mb() + 1);
- }
-
- void SetModerate() {
- SetMemoryFree(moderate_threshold_mb() - 1);
- }
-
- void SetCritical() {
- SetMemoryFree(critical_threshold_mb() - 1);
- }
-
- private:
- bool GetSystemMemoryStatus(MEMORYSTATUSEX* mem_status) override {
- // Simply copy the memory status set by the test fixture.
- *mem_status = mem_status_;
- return true;
- }
-
- MEMORYSTATUSEX mem_status_;
-
- DISALLOW_COPY_AND_ASSIGN(TestMemoryPressureMonitor);
-};
-
-class WinMemoryPressureMonitorTest : public testing::Test {
- protected:
- void CalculateCurrentMemoryPressureLevelTest(
- TestMemoryPressureMonitor* monitor) {
-
- int mod = monitor->moderate_threshold_mb();
- monitor->SetMemoryFree(mod + 1);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- monitor->CalculateCurrentPressureLevel());
-
- monitor->SetMemoryFree(mod);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->CalculateCurrentPressureLevel());
-
- monitor->SetMemoryFree(mod - 1);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->CalculateCurrentPressureLevel());
-
- int crit = monitor->critical_threshold_mb();
- monitor->SetMemoryFree(crit + 1);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor->CalculateCurrentPressureLevel());
-
- monitor->SetMemoryFree(crit);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- monitor->CalculateCurrentPressureLevel());
-
- monitor->SetMemoryFree(crit - 1);
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- monitor->CalculateCurrentPressureLevel());
- }
-
- base::MessageLoopForUI message_loop_;
-};
-
-// Tests the fundamental direct calculation of memory pressure with automatic
-// small-memory thresholds.
-TEST_F(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevelSmall) {
- static const int kModerateMb =
- MemoryPressureMonitor::kSmallMemoryDefaultModerateThresholdMb;
- static const int kCriticalMb =
- MemoryPressureMonitor::kSmallMemoryDefaultCriticalThresholdMb;
-
- TestMemoryPressureMonitor monitor(false); // Small-memory model.
-
- EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb());
- EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb());
-
- ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor));
-}
-
-// Tests the fundamental direct calculation of memory pressure with automatic
-// large-memory thresholds.
-TEST_F(WinMemoryPressureMonitorTest, CalculateCurrentMemoryPressureLevelLarge) {
- static const int kModerateMb =
- MemoryPressureMonitor::kLargeMemoryDefaultModerateThresholdMb;
- static const int kCriticalMb =
- MemoryPressureMonitor::kLargeMemoryDefaultCriticalThresholdMb;
-
- TestMemoryPressureMonitor monitor(true); // Large-memory model.
-
- EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb());
- EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb());
-
- ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor));
-}
-
-// Tests the fundamental direct calculation of memory pressure with manually
-// specified threshold levels.
-TEST_F(WinMemoryPressureMonitorTest,
- CalculateCurrentMemoryPressureLevelCustom) {
- static const int kSystemMb = 512;
- static const int kModerateMb = 256;
- static const int kCriticalMb = 128;
-
- TestMemoryPressureMonitor monitor(kSystemMb, kModerateMb, kCriticalMb);
-
- EXPECT_EQ(kModerateMb, monitor.moderate_threshold_mb());
- EXPECT_EQ(kCriticalMb, monitor.critical_threshold_mb());
-
- ASSERT_NO_FATAL_FAILURE(CalculateCurrentMemoryPressureLevelTest(&monitor));
-}
-
-// This test tests the various transition states from memory pressure, looking
-// for the correct behavior on event reposting as well as state updates.
-TEST_F(WinMemoryPressureMonitorTest, CheckMemoryPressure) {
- // Large-memory.
- testing::StrictMock<TestMemoryPressureMonitor> monitor(true);
- MemoryPressureListener listener(
- base::Bind(&TestMemoryPressureMonitor::OnMemoryPressure,
- base::Unretained(&monitor)));
-
- // Checking the memory pressure at 0% load should not produce any
- // events.
- monitor.SetNone();
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- monitor.GetCurrentPressureLevel());
-
- // Setting the memory level to 80% should produce a moderate pressure level.
- EXPECT_CALL(monitor,
- OnMemoryPressure(MemoryPressureListener::
- MEMORY_PRESSURE_LEVEL_MODERATE));
- monitor.SetModerate();
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
-
- // Check that the event gets reposted after a while.
- for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
- if (i + 1 == monitor.kModeratePressureCooldownCycles) {
- EXPECT_CALL(monitor,
- OnMemoryPressure(MemoryPressureListener::
- MEMORY_PRESSURE_LEVEL_MODERATE));
- }
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
- }
-
- // Setting the memory usage to 99% should produce critical levels.
- EXPECT_CALL(monitor,
- OnMemoryPressure(MemoryPressureListener::
- MEMORY_PRESSURE_LEVEL_CRITICAL));
- monitor.SetCritical();
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
-
- // Calling it again should immediately produce a second call.
- EXPECT_CALL(monitor,
- OnMemoryPressure(MemoryPressureListener::
- MEMORY_PRESSURE_LEVEL_CRITICAL));
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_CRITICAL,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
-
- // When lowering the pressure again there should be a notification and the
- // pressure should go back to moderate.
- EXPECT_CALL(monitor,
- OnMemoryPressure(MemoryPressureListener::
- MEMORY_PRESSURE_LEVEL_MODERATE));
- monitor.SetModerate();
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
-
- // Check that the event gets reposted after a while.
- for (int i = 0; i < monitor.kModeratePressureCooldownCycles; ++i) {
- if (i + 1 == monitor.kModeratePressureCooldownCycles) {
- EXPECT_CALL(monitor,
- OnMemoryPressure(MemoryPressureListener::
- MEMORY_PRESSURE_LEVEL_MODERATE));
- }
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_MODERATE,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
- }
-
- // Going down to no pressure should not produce an notification.
- monitor.SetNone();
- monitor.CheckMemoryPressure();
- RunLoop().RunUntilIdle();
- EXPECT_EQ(MemoryPressureListener::MEMORY_PRESSURE_LEVEL_NONE,
- monitor.GetCurrentPressureLevel());
- testing::Mock::VerifyAndClearExpectations(&monitor);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/memory/platform_shared_memory_region_unittest.cc b/base/memory/platform_shared_memory_region_unittest.cc
deleted file mode 100644
index f4d3071..0000000
--- a/base/memory/platform_shared_memory_region_unittest.cc
+++ /dev/null
@@ -1,288 +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 "base/memory/shared_memory_mapping.h"
-#include "base/process/process_metrics.h"
-#include "base/sys_info.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_shared_memory_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-#include <mach/mach_vm.h>
-#endif
-
-namespace base {
-namespace subtle {
-
-const size_t kRegionSize = 1024;
-
-class PlatformSharedMemoryRegionTest : public ::testing::Test {};
-
-// Tests that a default constructed region is invalid and produces invalid
-// mappings.
-TEST_F(PlatformSharedMemoryRegionTest, DefaultConstructedRegionIsInvalid) {
- PlatformSharedMemoryRegion region;
- EXPECT_FALSE(region.IsValid());
- WritableSharedMemoryMapping mapping = MapForTesting(®ion);
- EXPECT_FALSE(mapping.IsValid());
- PlatformSharedMemoryRegion duplicate = region.Duplicate();
- EXPECT_FALSE(duplicate.IsValid());
- EXPECT_FALSE(region.ConvertToReadOnly());
-}
-
-// Tests that creating a region of 0 size returns an invalid region.
-TEST_F(PlatformSharedMemoryRegionTest, CreateRegionOfZeroSizeIsInvalid) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(0);
- EXPECT_FALSE(region.IsValid());
-
- PlatformSharedMemoryRegion region2 =
- PlatformSharedMemoryRegion::CreateUnsafe(0);
- EXPECT_FALSE(region2.IsValid());
-}
-
-// Tests that creating a region of size bigger than the integer max value
-// returns an invalid region.
-TEST_F(PlatformSharedMemoryRegionTest, CreateTooLargeRegionIsInvalid) {
- size_t too_large_region_size =
- static_cast<size_t>(std::numeric_limits<int>::max()) + 1;
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(too_large_region_size);
- EXPECT_FALSE(region.IsValid());
-
- PlatformSharedMemoryRegion region2 =
- PlatformSharedMemoryRegion::CreateUnsafe(too_large_region_size);
- EXPECT_FALSE(region2.IsValid());
-}
-
-// Tests that regions consistently report their size as the size requested at
-// creation time even if their allocation size is larger due to platform
-// constraints.
-TEST_F(PlatformSharedMemoryRegionTest, ReportedSizeIsRequestedSize) {
- constexpr size_t kTestSizes[] = {1, 2, 3, 64, 4096, 1024 * 1024};
- for (size_t size : kTestSizes) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(size);
- EXPECT_EQ(region.GetSize(), size);
-
- region.ConvertToReadOnly();
- EXPECT_EQ(region.GetSize(), size);
- }
-}
-
-// Tests that the platform-specific handle converted to read-only cannot be used
-// to perform a writable mapping with low-level system APIs like mmap().
-TEST_F(PlatformSharedMemoryRegionTest, ReadOnlyHandleIsNotWritable) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- EXPECT_TRUE(region.ConvertToReadOnly());
- EXPECT_EQ(region.GetMode(), PlatformSharedMemoryRegion::Mode::kReadOnly);
- EXPECT_TRUE(
- CheckReadOnlyPlatformSharedMemoryRegionForTesting(std::move(region)));
-}
-
-// Tests that the PassPlatformHandle() call invalidates the region.
-TEST_F(PlatformSharedMemoryRegionTest, InvalidAfterPass) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- ignore_result(region.PassPlatformHandle());
- EXPECT_FALSE(region.IsValid());
-}
-
-// Tests that the region is invalid after move.
-TEST_F(PlatformSharedMemoryRegionTest, InvalidAfterMove) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- PlatformSharedMemoryRegion moved_region = std::move(region);
- EXPECT_FALSE(region.IsValid());
- EXPECT_TRUE(moved_region.IsValid());
-}
-
-// Tests that calling Take() with the size parameter equal to zero returns an
-// invalid region.
-TEST_F(PlatformSharedMemoryRegionTest, TakeRegionOfZeroSizeIsInvalid) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- PlatformSharedMemoryRegion region2 = PlatformSharedMemoryRegion::Take(
- region.PassPlatformHandle(), region.GetMode(), 0, region.GetGUID());
- EXPECT_FALSE(region2.IsValid());
-}
-
-// Tests that calling Take() with the size parameter bigger than the integer max
-// value returns an invalid region.
-TEST_F(PlatformSharedMemoryRegionTest, TakeTooLargeRegionIsInvalid) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- PlatformSharedMemoryRegion region2 = PlatformSharedMemoryRegion::Take(
- region.PassPlatformHandle(), region.GetMode(),
- static_cast<size_t>(std::numeric_limits<int>::max()) + 1,
- region.GetGUID());
- EXPECT_FALSE(region2.IsValid());
-}
-
-// Tests that mapping bytes out of the region limits fails.
-TEST_F(PlatformSharedMemoryRegionTest, MapAtOutOfTheRegionLimitsTest) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- WritableSharedMemoryMapping mapping =
- MapAtForTesting(®ion, 0, region.GetSize() + 1);
- EXPECT_FALSE(mapping.IsValid());
-}
-
-// Tests that mapping with a size and offset causing overflow fails.
-TEST_F(PlatformSharedMemoryRegionTest, MapAtWithOverflowTest) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(
- SysInfo::VMAllocationGranularity() * 2);
- ASSERT_TRUE(region.IsValid());
- size_t size = std::numeric_limits<size_t>::max();
- size_t offset = SysInfo::VMAllocationGranularity();
- // |size| + |offset| should be below the region size due to overflow but
- // mapping a region with these parameters should be invalid.
- EXPECT_LT(size + offset, region.GetSize());
- WritableSharedMemoryMapping mapping = MapAtForTesting(®ion, offset, size);
- EXPECT_FALSE(mapping.IsValid());
-}
-
-#if defined(OS_POSIX) && !defined(OS_ANDROID) && !defined(OS_FUCHSIA) && \
- !defined(OS_MACOSX)
-// Tests that the second handle is closed after a conversion to read-only on
-// POSIX.
-TEST_F(PlatformSharedMemoryRegionTest,
- ConvertToReadOnlyInvalidatesSecondHandle) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- ASSERT_TRUE(region.ConvertToReadOnly());
- FDPair fds = region.GetPlatformHandle();
- EXPECT_LT(fds.readonly_fd, 0);
-}
-#endif
-
-#if defined(OS_MACOSX) && !defined(OS_IOS)
-// Tests that protection bits are set correctly for read-only region on MacOS.
-TEST_F(PlatformSharedMemoryRegionTest, MapCurrentAndMaxProtectionSetCorrectly) {
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- ASSERT_TRUE(region.ConvertToReadOnly());
- WritableSharedMemoryMapping ro_mapping = MapForTesting(®ion);
- ASSERT_TRUE(ro_mapping.IsValid());
-
- vm_region_basic_info_64 basic_info;
- mach_vm_size_t dummy_size = 0;
- void* temp_addr = ro_mapping.memory();
- MachVMRegionResult result = GetBasicInfo(
- mach_task_self(), &dummy_size,
- reinterpret_cast<mach_vm_address_t*>(&temp_addr), &basic_info);
- EXPECT_EQ(result, MachVMRegionResult::Success);
- EXPECT_EQ(basic_info.protection & VM_PROT_ALL, VM_PROT_READ);
- EXPECT_EQ(basic_info.max_protection & VM_PROT_ALL, VM_PROT_READ);
-}
-#endif
-
-// Tests that platform handle permissions are checked correctly.
-TEST_F(PlatformSharedMemoryRegionTest,
- CheckPlatformHandlePermissionsCorrespondToMode) {
- using Mode = PlatformSharedMemoryRegion::Mode;
- auto check = [](const PlatformSharedMemoryRegion& region,
- PlatformSharedMemoryRegion::Mode mode) {
- return PlatformSharedMemoryRegion::
- CheckPlatformHandlePermissionsCorrespondToMode(
- region.GetPlatformHandle(), mode, region.GetSize());
- };
-
- // Check kWritable region.
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- EXPECT_TRUE(check(region, Mode::kWritable));
- EXPECT_FALSE(check(region, Mode::kReadOnly));
-
- // Check kReadOnly region.
- ASSERT_TRUE(region.ConvertToReadOnly());
- EXPECT_TRUE(check(region, Mode::kReadOnly));
- EXPECT_FALSE(check(region, Mode::kWritable));
- EXPECT_FALSE(check(region, Mode::kUnsafe));
-
- // Check kUnsafe region.
- PlatformSharedMemoryRegion region2 =
- PlatformSharedMemoryRegion::CreateUnsafe(kRegionSize);
- ASSERT_TRUE(region2.IsValid());
- EXPECT_TRUE(check(region2, Mode::kUnsafe));
- EXPECT_FALSE(check(region2, Mode::kReadOnly));
-}
-
-// Tests that it's impossible to create read-only platform shared memory region.
-TEST_F(PlatformSharedMemoryRegionTest, CreateReadOnlyRegionDeathTest) {
-#ifdef OFFICIAL_BUILD
- // The official build does not print the reason a CHECK failed.
- const char kErrorRegex[] = "";
-#else
- const char kErrorRegex[] =
- "Creating a region in read-only mode will lead to this region being "
- "non-modifiable";
-#endif
- EXPECT_DEATH_IF_SUPPORTED(
- PlatformSharedMemoryRegion::Create(
- PlatformSharedMemoryRegion::Mode::kReadOnly, kRegionSize),
- kErrorRegex);
-}
-
-// Tests that it's prohibited to duplicate a writable region.
-TEST_F(PlatformSharedMemoryRegionTest, DuplicateWritableRegionDeathTest) {
-#ifdef OFFICIAL_BUILD
- const char kErrorRegex[] = "";
-#else
- const char kErrorRegex[] =
- "Duplicating a writable shared memory region is prohibited";
-#endif
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- EXPECT_DEATH_IF_SUPPORTED(region.Duplicate(), kErrorRegex);
-}
-
-// Tests that it's prohibited to convert an unsafe region to read-only.
-TEST_F(PlatformSharedMemoryRegionTest, UnsafeRegionConvertToReadOnlyDeathTest) {
-#ifdef OFFICIAL_BUILD
- const char kErrorRegex[] = "";
-#else
- const char kErrorRegex[] =
- "Only writable shared memory region can be converted to read-only";
-#endif
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateUnsafe(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- EXPECT_DEATH_IF_SUPPORTED(region.ConvertToReadOnly(), kErrorRegex);
-}
-
-// Tests that it's prohibited to convert a read-only region to read-only.
-TEST_F(PlatformSharedMemoryRegionTest,
- ReadOnlyRegionConvertToReadOnlyDeathTest) {
-#ifdef OFFICIAL_BUILD
- const char kErrorRegex[] = "";
-#else
- const char kErrorRegex[] =
- "Only writable shared memory region can be converted to read-only";
-#endif
- PlatformSharedMemoryRegion region =
- PlatformSharedMemoryRegion::CreateWritable(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- EXPECT_TRUE(region.ConvertToReadOnly());
- EXPECT_DEATH_IF_SUPPORTED(region.ConvertToReadOnly(), kErrorRegex);
-}
-
-} // namespace subtle
-} // namespace base
diff --git a/base/memory/protected_memory_unittest.cc b/base/memory/protected_memory_unittest.cc
deleted file mode 100644
index b6ec61d..0000000
--- a/base/memory/protected_memory_unittest.cc
+++ /dev/null
@@ -1,117 +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/protected_memory.h"
-#include "base/memory/protected_memory_cfi.h"
-#include "base/synchronization/lock.h"
-#include "base/test/gtest_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-struct Data {
- Data() = default;
- Data(int foo_) : foo(foo_) {}
- int foo;
-};
-
-} // namespace
-
-class ProtectedMemoryTest : public ::testing::Test {
- protected:
- // Run tests one at a time. Some of the negative tests can not be made thread
- // safe.
- void SetUp() final { lock.Acquire(); }
- void TearDown() final { lock.Release(); }
-
- Lock lock;
-};
-
-PROTECTED_MEMORY_SECTION ProtectedMemory<int> init;
-
-TEST_F(ProtectedMemoryTest, Initializer) {
- static ProtectedMemory<int>::Initializer I(&init, 4);
- EXPECT_EQ(*init, 4);
-}
-
-PROTECTED_MEMORY_SECTION ProtectedMemory<Data> data;
-
-TEST_F(ProtectedMemoryTest, Basic) {
- AutoWritableMemory writer = AutoWritableMemory::Create(data);
- data->foo = 5;
- EXPECT_EQ(data->foo, 5);
-}
-
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-
-#if PROTECTED_MEMORY_ENABLED
-TEST_F(ProtectedMemoryTest, ReadOnlyOnStart) {
- EXPECT_DEATH({ data->foo = 6; AutoWritableMemory::Create(data); }, "");
-}
-
-TEST_F(ProtectedMemoryTest, ReadOnlyAfterSetWritable) {
- { AutoWritableMemory writer = AutoWritableMemory::Create(data); }
- EXPECT_DEATH({ data->foo = 7; }, "");
-}
-
-TEST_F(ProtectedMemoryTest, AssertMemoryIsReadOnly) {
- AssertMemoryIsReadOnly(&data->foo);
- { AutoWritableMemory::Create(data); }
- AssertMemoryIsReadOnly(&data->foo);
-
- ProtectedMemory<Data> writable_data;
- EXPECT_DCHECK_DEATH({ AssertMemoryIsReadOnly(&writable_data->foo); });
-}
-
-TEST_F(ProtectedMemoryTest, FailsIfDefinedOutsideOfProtectMemoryRegion) {
- ProtectedMemory<Data> data;
- EXPECT_DCHECK_DEATH({ AutoWritableMemory::Create(data); });
-}
-
-TEST_F(ProtectedMemoryTest, UnsanitizedCfiCallOutsideOfProtectedMemoryRegion) {
- ProtectedMemory<void (*)(void)> data;
- EXPECT_DCHECK_DEATH({ UnsanitizedCfiCall(data)(); });
-}
-#endif // PROTECTED_MEMORY_ENABLED
-
-namespace {
-
-struct BadIcall {
- BadIcall() = default;
- BadIcall(int (*fp_)(int)) : fp(fp_) {}
- int (*fp)(int);
-};
-
-unsigned int bad_icall(int i) {
- return 4 + i;
-}
-
-} // namespace
-
-PROTECTED_MEMORY_SECTION ProtectedMemory<BadIcall> icall_pm1;
-
-TEST_F(ProtectedMemoryTest, BadMemberCall) {
- static ProtectedMemory<BadIcall>::Initializer I(
- &icall_pm1, BadIcall(reinterpret_cast<int (*)(int)>(&bad_icall)));
-
- EXPECT_EQ(UnsanitizedCfiCall(icall_pm1, &BadIcall::fp)(1), 5);
- EXPECT_EQ(icall_pm1->fp(1), 5);
-}
-
-PROTECTED_MEMORY_SECTION ProtectedMemory<int (*)(int)> icall_pm2;
-
-TEST_F(ProtectedMemoryTest, BadFnPtrCall) {
- static ProtectedMemory<int (*)(int)>::Initializer I(
- &icall_pm2, reinterpret_cast<int (*)(int)>(&bad_icall));
-
- EXPECT_EQ(UnsanitizedCfiCall(icall_pm2)(1), 5);
- EXPECT_EQ((*icall_pm2)(1), 5);
-}
-
-#endif // defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-
-} // namespace base
diff --git a/base/memory/ptr_util_unittest.cc b/base/memory/ptr_util_unittest.cc
deleted file mode 100644
index 3fa40d8..0000000
--- 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_memory_unittest.cc b/base/memory/ref_counted_memory_unittest.cc
deleted file mode 100644
index b7498f9..0000000
--- a/base/memory/ref_counted_memory_unittest.cc
+++ /dev/null
@@ -1,145 +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/memory/ref_counted_memory.h"
-
-#include <stdint.h>
-
-#include <utility>
-
-#include "base/memory/read_only_shared_memory_region.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using testing::Each;
-using testing::ElementsAre;
-
-namespace base {
-
-TEST(RefCountedMemoryUnitTest, RefCountedStaticMemory) {
- auto mem = MakeRefCounted<RefCountedStaticMemory>("static mem00", 10);
-
- EXPECT_EQ(10U, mem->size());
- EXPECT_EQ("static mem", std::string(mem->front_as<char>(), mem->size()));
-}
-
-TEST(RefCountedMemoryUnitTest, RefCountedBytes) {
- std::vector<uint8_t> data;
- data.push_back(45);
- data.push_back(99);
- scoped_refptr<RefCountedMemory> mem = RefCountedBytes::TakeVector(&data);
-
- EXPECT_EQ(0U, data.size());
-
- ASSERT_EQ(2U, mem->size());
- EXPECT_EQ(45U, mem->front()[0]);
- EXPECT_EQ(99U, mem->front()[1]);
-
- scoped_refptr<RefCountedMemory> mem2;
- {
- const unsigned char kData[] = {12, 11, 99};
- mem2 = MakeRefCounted<RefCountedBytes>(kData, arraysize(kData));
- }
- ASSERT_EQ(3U, mem2->size());
- EXPECT_EQ(12U, mem2->front()[0]);
- EXPECT_EQ(11U, mem2->front()[1]);
- EXPECT_EQ(99U, mem2->front()[2]);
-}
-
-TEST(RefCountedMemoryUnitTest, RefCountedBytesMutable) {
- auto mem = base::MakeRefCounted<RefCountedBytes>(10);
-
- ASSERT_EQ(10U, mem->size());
- EXPECT_THAT(mem->data(), Each(0U));
-
- // Test non-const versions of data(), front() and front_as<>().
- mem->data()[0] = 1;
- mem->front()[1] = 2;
- mem->front_as<char>()[2] = 3;
-
- EXPECT_THAT(mem->data(), ElementsAre(1, 2, 3, 0, 0, 0, 0, 0, 0, 0));
-}
-
-TEST(RefCountedMemoryUnitTest, RefCountedString) {
- std::string s("destroy me");
- scoped_refptr<RefCountedMemory> mem = RefCountedString::TakeString(&s);
-
- EXPECT_EQ(0U, s.size());
-
- ASSERT_EQ(10U, mem->size());
- EXPECT_EQ('d', mem->front()[0]);
- EXPECT_EQ('e', mem->front()[1]);
- EXPECT_EQ('e', mem->front()[9]);
-}
-
-TEST(RefCountedMemoryUnitTest, RefCountedSharedMemory) {
- static const char kData[] = "shm_dummy_data";
- auto shm = std::make_unique<SharedMemory>();
- ASSERT_TRUE(shm->CreateAndMapAnonymous(sizeof(kData)));
- memcpy(shm->memory(), kData, sizeof(kData));
-
- auto mem =
- MakeRefCounted<RefCountedSharedMemory>(std::move(shm), sizeof(kData));
- ASSERT_EQ(sizeof(kData), mem->size());
- EXPECT_EQ('s', mem->front()[0]);
- EXPECT_EQ('h', mem->front()[1]);
- EXPECT_EQ('_', mem->front()[9]);
-}
-
-TEST(RefCountedMemoryUnitTest, RefCountedSharedMemoryMapping) {
- static const char kData[] = "mem_region_dummy_data";
- scoped_refptr<RefCountedSharedMemoryMapping> mem;
- {
- MappedReadOnlyRegion region =
- ReadOnlySharedMemoryRegion::Create(sizeof(kData));
- ReadOnlySharedMemoryMapping ro_mapping = region.region.Map();
- WritableSharedMemoryMapping rw_mapping = std::move(region.mapping);
- ASSERT_TRUE(rw_mapping.IsValid());
- memcpy(rw_mapping.memory(), kData, sizeof(kData));
- mem = MakeRefCounted<RefCountedSharedMemoryMapping>(std::move(ro_mapping));
- }
-
- ASSERT_LE(sizeof(kData), mem->size());
- EXPECT_EQ('e', mem->front()[1]);
- EXPECT_EQ('m', mem->front()[2]);
- EXPECT_EQ('o', mem->front()[8]);
-
- {
- MappedReadOnlyRegion region =
- ReadOnlySharedMemoryRegion::Create(sizeof(kData));
- WritableSharedMemoryMapping rw_mapping = std::move(region.mapping);
- ASSERT_TRUE(rw_mapping.IsValid());
- memcpy(rw_mapping.memory(), kData, sizeof(kData));
- mem = RefCountedSharedMemoryMapping::CreateFromWholeRegion(region.region);
- }
-
- ASSERT_LE(sizeof(kData), mem->size());
- EXPECT_EQ('_', mem->front()[3]);
- EXPECT_EQ('r', mem->front()[4]);
- EXPECT_EQ('i', mem->front()[7]);
-}
-
-TEST(RefCountedMemoryUnitTest, Equals) {
- std::string s1("same");
- scoped_refptr<RefCountedMemory> mem1 = RefCountedString::TakeString(&s1);
-
- std::vector<unsigned char> d2 = {'s', 'a', 'm', 'e'};
- scoped_refptr<RefCountedMemory> mem2 = RefCountedBytes::TakeVector(&d2);
-
- EXPECT_TRUE(mem1->Equals(mem2));
-
- std::string s3("diff");
- scoped_refptr<RefCountedMemory> mem3 = RefCountedString::TakeString(&s3);
-
- EXPECT_FALSE(mem1->Equals(mem3));
- EXPECT_FALSE(mem2->Equals(mem3));
-}
-
-TEST(RefCountedMemoryUnitTest, EqualsNull) {
- std::string s("str");
- scoped_refptr<RefCountedMemory> mem = RefCountedString::TakeString(&s);
- EXPECT_FALSE(mem->Equals(nullptr));
-}
-
-} // namespace base
diff --git a/base/memory/ref_counted_unittest.cc b/base/memory/ref_counted_unittest.cc
deleted file mode 100644
index d88fc54..0000000
--- a/base/memory/ref_counted_unittest.cc
+++ /dev/null
@@ -1,606 +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/memory/ref_counted.h"
-
-#include <type_traits>
-#include <utility>
-
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class SelfAssign : public base::RefCounted<SelfAssign> {
- protected:
- virtual ~SelfAssign() = default;
-
- private:
- friend class base::RefCounted<SelfAssign>;
-};
-
-class Derived : public SelfAssign {
- protected:
- ~Derived() override = default;
-
- private:
- friend class base::RefCounted<Derived>;
-};
-
-class CheckDerivedMemberAccess : public scoped_refptr<SelfAssign> {
- public:
- CheckDerivedMemberAccess() {
- // This shouldn't compile if we don't have access to the member variable.
- SelfAssign** pptr = &ptr_;
- EXPECT_EQ(*pptr, ptr_);
- }
-};
-
-class ScopedRefPtrToSelf : public base::RefCounted<ScopedRefPtrToSelf> {
- public:
- ScopedRefPtrToSelf() : self_ptr_(this) {}
-
- static bool was_destroyed() { return was_destroyed_; }
-
- static void reset_was_destroyed() { was_destroyed_ = false; }
-
- scoped_refptr<ScopedRefPtrToSelf> self_ptr_;
-
- private:
- friend class base::RefCounted<ScopedRefPtrToSelf>;
- ~ScopedRefPtrToSelf() { was_destroyed_ = true; }
-
- static bool was_destroyed_;
-};
-
-bool ScopedRefPtrToSelf::was_destroyed_ = false;
-
-class ScopedRefPtrCountBase : public base::RefCounted<ScopedRefPtrCountBase> {
- public:
- ScopedRefPtrCountBase() { ++constructor_count_; }
-
- static int constructor_count() { return constructor_count_; }
-
- static int destructor_count() { return destructor_count_; }
-
- static void reset_count() {
- constructor_count_ = 0;
- destructor_count_ = 0;
- }
-
- protected:
- virtual ~ScopedRefPtrCountBase() { ++destructor_count_; }
-
- private:
- friend class base::RefCounted<ScopedRefPtrCountBase>;
-
- static int constructor_count_;
- static int destructor_count_;
-};
-
-int ScopedRefPtrCountBase::constructor_count_ = 0;
-int ScopedRefPtrCountBase::destructor_count_ = 0;
-
-class ScopedRefPtrCountDerived : public ScopedRefPtrCountBase {
- public:
- ScopedRefPtrCountDerived() { ++constructor_count_; }
-
- static int constructor_count() { return constructor_count_; }
-
- static int destructor_count() { return destructor_count_; }
-
- static void reset_count() {
- constructor_count_ = 0;
- destructor_count_ = 0;
- }
-
- protected:
- ~ScopedRefPtrCountDerived() override { ++destructor_count_; }
-
- private:
- friend class base::RefCounted<ScopedRefPtrCountDerived>;
-
- static int constructor_count_;
- static int destructor_count_;
-};
-
-int ScopedRefPtrCountDerived::constructor_count_ = 0;
-int ScopedRefPtrCountDerived::destructor_count_ = 0;
-
-class Other : public base::RefCounted<Other> {
- private:
- friend class base::RefCounted<Other>;
-
- ~Other() = default;
-};
-
-class HasPrivateDestructorWithDeleter;
-
-struct Deleter {
- static void Destruct(const HasPrivateDestructorWithDeleter* x);
-};
-
-class HasPrivateDestructorWithDeleter
- : public base::RefCounted<HasPrivateDestructorWithDeleter, Deleter> {
- public:
- HasPrivateDestructorWithDeleter() = default;
-
- private:
- friend struct Deleter;
- ~HasPrivateDestructorWithDeleter() = default;
-};
-
-void Deleter::Destruct(const HasPrivateDestructorWithDeleter* x) {
- delete x;
-}
-
-scoped_refptr<Other> Overloaded(scoped_refptr<Other> other) {
- return other;
-}
-
-scoped_refptr<SelfAssign> Overloaded(scoped_refptr<SelfAssign> self_assign) {
- return self_assign;
-}
-
-class InitialRefCountIsOne : public base::RefCounted<InitialRefCountIsOne> {
- public:
- REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE();
-
- InitialRefCountIsOne() = default;
-
- private:
- friend class base::RefCounted<InitialRefCountIsOne>;
- ~InitialRefCountIsOne() = default;
-};
-
-} // end namespace
-
-TEST(RefCountedUnitTest, TestSelfAssignment) {
- SelfAssign* p = new SelfAssign;
- scoped_refptr<SelfAssign> var(p);
- var = *&var; // The *& defeats Clang's -Wself-assign warning.
- EXPECT_EQ(var.get(), p);
- var = std::move(var);
- EXPECT_EQ(var.get(), p);
- var.swap(var);
- EXPECT_EQ(var.get(), p);
- swap(var, var);
- EXPECT_EQ(var.get(), p);
-}
-
-TEST(RefCountedUnitTest, ScopedRefPtrMemberAccess) {
- CheckDerivedMemberAccess check;
-}
-
-TEST(RefCountedUnitTest, ScopedRefPtrToSelfPointerAssignment) {
- ScopedRefPtrToSelf::reset_was_destroyed();
-
- ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
- EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
- check->self_ptr_ = nullptr;
- EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
-}
-
-TEST(RefCountedUnitTest, ScopedRefPtrToSelfMoveAssignment) {
- ScopedRefPtrToSelf::reset_was_destroyed();
-
- ScopedRefPtrToSelf* check = new ScopedRefPtrToSelf();
- EXPECT_FALSE(ScopedRefPtrToSelf::was_destroyed());
- // Releasing |check->self_ptr_| will delete |check|.
- // The move assignment operator must assign |check->self_ptr_| first then
- // release |check->self_ptr_|.
- check->self_ptr_ = scoped_refptr<ScopedRefPtrToSelf>();
- EXPECT_TRUE(ScopedRefPtrToSelf::was_destroyed());
-}
-
-TEST(RefCountedUnitTest, BooleanTesting) {
- scoped_refptr<SelfAssign> ptr_to_an_instance = new SelfAssign;
- EXPECT_TRUE(ptr_to_an_instance);
- EXPECT_FALSE(!ptr_to_an_instance);
-
- if (ptr_to_an_instance) {
- } else {
- ADD_FAILURE() << "Pointer to an instance should result in true.";
- }
-
- if (!ptr_to_an_instance) { // check for operator!().
- ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
- }
-
- scoped_refptr<SelfAssign> null_ptr;
- EXPECT_FALSE(null_ptr);
- EXPECT_TRUE(!null_ptr);
-
- if (null_ptr) {
- ADD_FAILURE() << "Null pointer should result in false.";
- }
-
- if (!null_ptr) { // check for operator!().
- } else {
- ADD_FAILURE() << "Null pointer should result in !x being true.";
- }
-}
-
-TEST(RefCountedUnitTest, Equality) {
- scoped_refptr<SelfAssign> p1(new SelfAssign);
- scoped_refptr<SelfAssign> p2(new SelfAssign);
-
- EXPECT_EQ(p1, p1);
- EXPECT_EQ(p2, p2);
-
- EXPECT_NE(p1, p2);
- EXPECT_NE(p2, p1);
-}
-
-TEST(RefCountedUnitTest, NullptrEquality) {
- scoped_refptr<SelfAssign> ptr_to_an_instance(new SelfAssign);
- scoped_refptr<SelfAssign> ptr_to_nullptr;
-
- EXPECT_NE(nullptr, ptr_to_an_instance);
- EXPECT_NE(ptr_to_an_instance, nullptr);
- EXPECT_EQ(nullptr, ptr_to_nullptr);
- EXPECT_EQ(ptr_to_nullptr, nullptr);
-}
-
-TEST(RefCountedUnitTest, ConvertibleEquality) {
- scoped_refptr<Derived> p1(new Derived);
- scoped_refptr<SelfAssign> p2;
-
- EXPECT_NE(p1, p2);
- EXPECT_NE(p2, p1);
-
- p2 = p1;
-
- EXPECT_EQ(p1, p2);
- EXPECT_EQ(p2, p1);
-}
-
-TEST(RefCountedUnitTest, MoveAssignment1) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1(raw);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- {
- scoped_refptr<ScopedRefPtrCountBase> p2;
-
- p2 = std::move(p1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(nullptr, p1.get());
- EXPECT_EQ(raw, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveAssignment2) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1;
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- {
- scoped_refptr<ScopedRefPtrCountBase> p2(raw);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- p1 = std::move(p2);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(raw, p1.get());
- EXPECT_EQ(nullptr, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveAssignmentSameInstance1) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1(raw);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- {
- scoped_refptr<ScopedRefPtrCountBase> p2(p1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- p1 = std::move(p2);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(raw, p1.get());
- EXPECT_EQ(nullptr, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveAssignmentSameInstance2) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1(raw);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- {
- scoped_refptr<ScopedRefPtrCountBase> p2(p1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- p2 = std::move(p1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(nullptr, p1.get());
- EXPECT_EQ(raw, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveAssignmentDifferentInstances) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- {
- ScopedRefPtrCountBase *raw2 = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p2(raw2);
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- p1 = std::move(p2);
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(raw2, p1.get());
- EXPECT_EQ(nullptr, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveAssignmentSelfMove) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase* raw = new ScopedRefPtrCountBase;
- scoped_refptr<ScopedRefPtrCountBase> p1(raw);
- scoped_refptr<ScopedRefPtrCountBase>& p1_ref = p1;
-
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- p1 = std::move(p1_ref);
-
- // |p1| is "valid but unspecified", so don't bother inspecting its
- // contents, just ensure that we don't crash.
- }
-
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveAssignmentDerived) {
- ScopedRefPtrCountBase::reset_count();
- ScopedRefPtrCountDerived::reset_count();
-
- {
- ScopedRefPtrCountBase *raw1 = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1(raw1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
-
- {
- ScopedRefPtrCountDerived *raw2 = new ScopedRefPtrCountDerived();
- scoped_refptr<ScopedRefPtrCountDerived> p2(raw2);
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
-
- p1 = std::move(p2);
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
- EXPECT_EQ(raw2, p1.get());
- EXPECT_EQ(nullptr, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(2, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(2, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveConstructor) {
- ScopedRefPtrCountBase::reset_count();
-
- {
- ScopedRefPtrCountBase *raw = new ScopedRefPtrCountBase();
- scoped_refptr<ScopedRefPtrCountBase> p1(raw);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
-
- {
- scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(nullptr, p1.get());
- EXPECT_EQ(raw, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
-}
-
-TEST(RefCountedUnitTest, MoveConstructorDerived) {
- ScopedRefPtrCountBase::reset_count();
- ScopedRefPtrCountDerived::reset_count();
-
- {
- ScopedRefPtrCountDerived *raw1 = new ScopedRefPtrCountDerived();
- scoped_refptr<ScopedRefPtrCountDerived> p1(raw1);
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
-
- {
- scoped_refptr<ScopedRefPtrCountBase> p2(std::move(p1));
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(0, ScopedRefPtrCountDerived::destructor_count());
- EXPECT_EQ(nullptr, p1.get());
- EXPECT_EQ(raw1, p2.get());
-
- // p2 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
-
- // p1 goes out of scope.
- }
- EXPECT_EQ(1, ScopedRefPtrCountBase::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountBase::destructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::constructor_count());
- EXPECT_EQ(1, ScopedRefPtrCountDerived::destructor_count());
-}
-
-TEST(RefCountedUnitTest, TestOverloadResolutionCopy) {
- const scoped_refptr<Derived> derived(new Derived);
- const scoped_refptr<SelfAssign> expected(derived);
- EXPECT_EQ(expected, Overloaded(derived));
-
- const scoped_refptr<Other> other(new Other);
- EXPECT_EQ(other, Overloaded(other));
-}
-
-TEST(RefCountedUnitTest, TestOverloadResolutionMove) {
- scoped_refptr<Derived> derived(new Derived);
- const scoped_refptr<SelfAssign> expected(derived);
- EXPECT_EQ(expected, Overloaded(std::move(derived)));
-
- scoped_refptr<Other> other(new Other);
- const scoped_refptr<Other> other2(other);
- EXPECT_EQ(other2, Overloaded(std::move(other)));
-}
-
-TEST(RefCountedUnitTest, TestMakeRefCounted) {
- scoped_refptr<Derived> derived = new Derived;
- EXPECT_TRUE(derived->HasOneRef());
- derived = nullptr;
-
- scoped_refptr<Derived> derived2 = base::MakeRefCounted<Derived>();
- EXPECT_TRUE(derived2->HasOneRef());
- derived2 = nullptr;
-}
-
-TEST(RefCountedUnitTest, TestInitialRefCountIsOne) {
- scoped_refptr<InitialRefCountIsOne> obj =
- base::MakeRefCounted<InitialRefCountIsOne>();
- EXPECT_TRUE(obj->HasOneRef());
- obj = nullptr;
-
- scoped_refptr<InitialRefCountIsOne> obj2 =
- base::AdoptRef(new InitialRefCountIsOne);
- EXPECT_TRUE(obj2->HasOneRef());
- obj2 = nullptr;
-
- scoped_refptr<Other> obj3 = base::MakeRefCounted<Other>();
- EXPECT_TRUE(obj3->HasOneRef());
- obj3 = nullptr;
-}
-
-TEST(RefCountedDeathTest, TestAdoptRef) {
- // Check that WrapRefCounted() DCHECKs if passed a type that defines
- // REQUIRE_ADOPTION_FOR_REFCOUNTED_TYPE.
- EXPECT_DCHECK_DEATH(base::WrapRefCounted(new InitialRefCountIsOne));
-
- // Check that AdoptRef() DCHECKs if passed a nullptr.
- InitialRefCountIsOne* ptr = nullptr;
- EXPECT_DCHECK_DEATH(base::AdoptRef(ptr));
-
- // Check that AdoptRef() DCHECKs if passed an object that doesn't need to be
- // adopted.
- scoped_refptr<InitialRefCountIsOne> obj =
- base::MakeRefCounted<InitialRefCountIsOne>();
- EXPECT_DCHECK_DEATH(base::AdoptRef(obj.get()));
-}
-
-TEST(RefCountedUnitTest, TestPrivateDestructorWithDeleter) {
- // Ensure that RefCounted doesn't need the access to the pointee dtor when
- // a custom deleter is given.
- scoped_refptr<HasPrivateDestructorWithDeleter> obj =
- base::MakeRefCounted<HasPrivateDestructorWithDeleter>();
-}
diff --git a/base/memory/ref_counted_unittest.nc b/base/memory/ref_counted_unittest.nc
deleted file mode 100644
index b8c371f..0000000
--- 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_mac_unittest.cc b/base/memory/shared_memory_mac_unittest.cc
deleted file mode 100644
index b17dab7..0000000
--- a/base/memory/shared_memory_mac_unittest.cc
+++ /dev/null
@@ -1,457 +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 <mach/mach.h>
-#include <mach/mach_vm.h>
-#include <servers/bootstrap.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/command_line.h"
-#include "base/mac/mac_util.h"
-#include "base/mac/mach_logging.h"
-#include "base/mac/scoped_mach_port.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory.h"
-#include "base/process/process_handle.h"
-#include "base/rand_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "base/unguessable_token.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-
-namespace {
-
-// Gets the current and maximum protection levels of the memory region.
-// Returns whether the operation was successful.
-// |current| and |max| are output variables only populated on success.
-bool GetProtections(void* address, size_t size, int* current, int* max) {
- vm_region_info_t region_info;
- mach_vm_address_t mem_address = reinterpret_cast<mach_vm_address_t>(address);
- mach_vm_size_t mem_size = size;
- vm_region_basic_info_64 basic_info;
-
- region_info = reinterpret_cast<vm_region_recurse_info_t>(&basic_info);
- vm_region_flavor_t flavor = VM_REGION_BASIC_INFO_64;
- memory_object_name_t memory_object;
- mach_msg_type_number_t count = VM_REGION_BASIC_INFO_COUNT_64;
-
- kern_return_t kr =
- mach_vm_region(mach_task_self(), &mem_address, &mem_size, flavor,
- region_info, &count, &memory_object);
- if (kr != KERN_SUCCESS) {
- MACH_LOG(ERROR, kr) << "Failed to get region info.";
- return false;
- }
-
- *current = basic_info.protection;
- *max = basic_info.max_protection;
- return true;
-}
-
-// Creates a new SharedMemory with the given |size|, filled with 'a'.
-std::unique_ptr<SharedMemory> CreateSharedMemory(int size) {
- SharedMemoryHandle shm(size, UnguessableToken::Create());
- if (!shm.IsValid()) {
- LOG(ERROR) << "Failed to make SharedMemoryHandle";
- return nullptr;
- }
- std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false));
- shared_memory->Map(size);
- memset(shared_memory->memory(), 'a', size);
- return shared_memory;
-}
-
-static const std::string g_service_switch_name = "service_name";
-
-// Structs used to pass a mach port from client to server.
-struct MachSendPortMessage {
- mach_msg_header_t header;
- mach_msg_body_t body;
- mach_msg_port_descriptor_t data;
-};
-struct MachReceivePortMessage {
- mach_msg_header_t header;
- mach_msg_body_t body;
- mach_msg_port_descriptor_t data;
- mach_msg_trailer_t trailer;
-};
-
-// Makes the current process into a Mach Server with the given |service_name|.
-mach_port_t BecomeMachServer(const char* service_name) {
- mach_port_t port;
- kern_return_t kr = bootstrap_check_in(bootstrap_port, service_name, &port);
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "BecomeMachServer";
- return port;
-}
-
-// Returns the mach port for the Mach Server with the given |service_name|.
-mach_port_t LookupServer(const char* service_name) {
- mach_port_t server_port;
- kern_return_t kr =
- bootstrap_look_up(bootstrap_port, service_name, &server_port);
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "LookupServer";
- return server_port;
-}
-
-mach_port_t MakeReceivingPort() {
- mach_port_t client_port;
- kern_return_t kr =
- mach_port_allocate(mach_task_self(), // our task is acquiring
- MACH_PORT_RIGHT_RECEIVE, // a new receive right
- &client_port); // with this name
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "MakeReceivingPort";
- return client_port;
-}
-
-// Blocks until a mach message is sent to |server_port|. This mach message
-// must contain a mach port. Returns that mach port.
-mach_port_t ReceiveMachPort(mach_port_t port_to_listen_on) {
- MachReceivePortMessage recv_msg;
- mach_msg_header_t* recv_hdr = &(recv_msg.header);
- recv_hdr->msgh_local_port = port_to_listen_on;
- recv_hdr->msgh_size = sizeof(recv_msg);
- kern_return_t kr =
- mach_msg(recv_hdr, // message buffer
- MACH_RCV_MSG, // option indicating service
- 0, // send size
- recv_hdr->msgh_size, // size of header + body
- port_to_listen_on, // receive name
- MACH_MSG_TIMEOUT_NONE, // no timeout, wait forever
- MACH_PORT_NULL); // no notification port
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "ReceiveMachPort";
- mach_port_t other_task_port = recv_msg.data.name;
- return other_task_port;
-}
-
-// Passes a copy of the send right of |port_to_send| to |receiving_port|.
-void SendMachPort(mach_port_t receiving_port,
- mach_port_t port_to_send,
- int disposition) {
- MachSendPortMessage send_msg;
- mach_msg_header_t* send_hdr;
- send_hdr = &(send_msg.header);
- send_hdr->msgh_bits =
- MACH_MSGH_BITS(MACH_MSG_TYPE_COPY_SEND, 0) | MACH_MSGH_BITS_COMPLEX;
- send_hdr->msgh_size = sizeof(send_msg);
- send_hdr->msgh_remote_port = receiving_port;
- send_hdr->msgh_local_port = MACH_PORT_NULL;
- send_hdr->msgh_reserved = 0;
- send_hdr->msgh_id = 0;
- send_msg.body.msgh_descriptor_count = 1;
- send_msg.data.name = port_to_send;
- send_msg.data.disposition = disposition;
- send_msg.data.type = MACH_MSG_PORT_DESCRIPTOR;
- int kr = mach_msg(send_hdr, // message buffer
- MACH_SEND_MSG, // option indicating send
- send_hdr->msgh_size, // size of header + body
- 0, // receive limit
- MACH_PORT_NULL, // receive name
- MACH_MSG_TIMEOUT_NONE, // no timeout, wait forever
- MACH_PORT_NULL); // no notification port
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "SendMachPort";
-}
-
-std::string CreateRandomServiceName() {
- return StringPrintf("SharedMemoryMacMultiProcessTest.%llu", RandUint64());
-}
-
-// Sets up the mach communication ports with the server. Returns a port to which
-// the server will send mach objects.
-mach_port_t CommonChildProcessSetUp() {
- CommandLine cmd_line = *CommandLine::ForCurrentProcess();
- std::string service_name =
- cmd_line.GetSwitchValueASCII(g_service_switch_name);
- mac::ScopedMachSendRight server_port(LookupServer(service_name.c_str()));
- mach_port_t client_port = MakeReceivingPort();
-
- // Send the port that this process is listening on to the server.
- SendMachPort(server_port.get(), client_port, MACH_MSG_TYPE_MAKE_SEND);
- return client_port;
-}
-
-// The number of active names in the current task's port name space.
-mach_msg_type_number_t GetActiveNameCount() {
- mach_port_name_array_t name_array;
- mach_msg_type_number_t names_count;
- mach_port_type_array_t type_array;
- mach_msg_type_number_t types_count;
- kern_return_t kr = mach_port_names(mach_task_self(), &name_array,
- &names_count, &type_array, &types_count);
- MACH_CHECK(kr == KERN_SUCCESS, kr) << "GetActiveNameCount";
- return names_count;
-}
-
-} // namespace
-
-class SharedMemoryMacMultiProcessTest : public MultiProcessTest {
- public:
- SharedMemoryMacMultiProcessTest() {}
-
- CommandLine MakeCmdLine(const std::string& procname) override {
- CommandLine command_line = MultiProcessTest::MakeCmdLine(procname);
- // Pass the service name to the child process.
- command_line.AppendSwitchASCII(g_service_switch_name, service_name_);
- return command_line;
- }
-
- void SetUpChild(const std::string& name) {
- // Make a random service name so that this test doesn't conflict with other
- // similar tests.
- service_name_ = CreateRandomServiceName();
- server_port_.reset(BecomeMachServer(service_name_.c_str()));
- child_process_ = SpawnChild(name);
- client_port_.reset(ReceiveMachPort(server_port_.get()));
- }
-
- static const int s_memory_size = 99999;
-
- protected:
- std::string service_name_;
-
- // A port on which the main process listens for mach messages from the child
- // process.
- mac::ScopedMachReceiveRight server_port_;
-
- // A port on which the child process listens for mach messages from the main
- // process.
- mac::ScopedMachSendRight client_port_;
-
- base::Process child_process_;
- DISALLOW_COPY_AND_ASSIGN(SharedMemoryMacMultiProcessTest);
-};
-
-// Tests that content written to shared memory in the server process can be read
-// by the child process.
-TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemory) {
- SetUpChild("MachBasedSharedMemoryClient");
-
- std::unique_ptr<SharedMemory> shared_memory(
- CreateSharedMemory(s_memory_size));
-
- // Send the underlying memory object to the client process.
- SendMachPort(client_port_.get(), shared_memory->handle().GetMemoryObject(),
- MACH_MSG_TYPE_COPY_SEND);
- int rv = -1;
- ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
- TestTimeouts::action_timeout(), &rv));
- EXPECT_EQ(0, rv);
-}
-
-MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryClient) {
- mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp());
- // The next mach port should be for a memory object.
- mach_port_t memory_object = ReceiveMachPort(client_port.get());
- SharedMemoryHandle shm(memory_object,
- SharedMemoryMacMultiProcessTest::s_memory_size,
- UnguessableToken::Create());
- SharedMemory shared_memory(shm, false);
- shared_memory.Map(SharedMemoryMacMultiProcessTest::s_memory_size);
- const char* start = static_cast<const char*>(shared_memory.memory());
- for (int i = 0; i < SharedMemoryMacMultiProcessTest::s_memory_size; ++i) {
- DCHECK_EQ(start[i], 'a');
- }
- return 0;
-}
-
-// Tests that mapping shared memory with an offset works correctly.
-TEST_F(SharedMemoryMacMultiProcessTest, MachBasedSharedMemoryWithOffset) {
- SetUpChild("MachBasedSharedMemoryWithOffsetClient");
-
- SharedMemoryHandle shm(s_memory_size, UnguessableToken::Create());
- ASSERT_TRUE(shm.IsValid());
- SharedMemory shared_memory(shm, false);
- shared_memory.Map(s_memory_size);
-
- size_t page_size = SysInfo::VMAllocationGranularity();
- char* start = static_cast<char*>(shared_memory.memory());
- memset(start, 'a', page_size);
- memset(start + page_size, 'b', page_size);
- memset(start + 2 * page_size, 'c', page_size);
-
- // Send the underlying memory object to the client process.
- SendMachPort(
- client_port_.get(), shm.GetMemoryObject(), MACH_MSG_TYPE_COPY_SEND);
- int rv = -1;
- ASSERT_TRUE(child_process_.WaitForExitWithTimeout(
- TestTimeouts::action_timeout(), &rv));
- EXPECT_EQ(0, rv);
-}
-
-MULTIPROCESS_TEST_MAIN(MachBasedSharedMemoryWithOffsetClient) {
- mac::ScopedMachReceiveRight client_port(CommonChildProcessSetUp());
- // The next mach port should be for a memory object.
- mach_port_t memory_object = ReceiveMachPort(client_port.get());
- SharedMemoryHandle shm(memory_object,
- SharedMemoryMacMultiProcessTest::s_memory_size,
- UnguessableToken::Create());
- SharedMemory shared_memory(shm, false);
- size_t page_size = SysInfo::VMAllocationGranularity();
- shared_memory.MapAt(page_size, 2 * page_size);
- const char* start = static_cast<const char*>(shared_memory.memory());
- for (size_t i = 0; i < page_size; ++i) {
- DCHECK_EQ(start[i], 'b');
- }
- for (size_t i = page_size; i < 2 * page_size; ++i) {
- DCHECK_EQ(start[i], 'c');
- }
- return 0;
-}
-
-// Tests that duplication and closing has the right effect on Mach reference
-// counts.
-TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicateAndClose) {
- mach_msg_type_number_t active_name_count = GetActiveNameCount();
-
- // Making a new SharedMemoryHandle increments the name count.
- SharedMemoryHandle shm(s_memory_size, UnguessableToken::Create());
- ASSERT_TRUE(shm.IsValid());
- EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
-
- // Duplicating the SharedMemoryHandle increments the ref count, but doesn't
- // make a new name.
- shm.Duplicate();
- EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
-
- // Closing the SharedMemoryHandle decrements the ref count. The first time has
- // no effect.
- shm.Close();
- EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
-
- // Closing the SharedMemoryHandle decrements the ref count. The second time
- // destroys the port.
- shm.Close();
- EXPECT_EQ(active_name_count, GetActiveNameCount());
-}
-
-// Tests that Mach shared memory can be mapped and unmapped.
-TEST_F(SharedMemoryMacMultiProcessTest, MachUnmapMap) {
- mach_msg_type_number_t active_name_count = GetActiveNameCount();
-
- std::unique_ptr<SharedMemory> shared_memory =
- CreateSharedMemory(s_memory_size);
- ASSERT_TRUE(shared_memory->Unmap());
- ASSERT_TRUE(shared_memory->Map(s_memory_size));
- shared_memory.reset();
- EXPECT_EQ(active_name_count, GetActiveNameCount());
-}
-
-// Tests that passing a SharedMemoryHandle to a SharedMemory object also passes
-// ownership, and that destroying the SharedMemory closes the SharedMemoryHandle
-// as well.
-TEST_F(SharedMemoryMacMultiProcessTest, MachSharedMemoryTakesOwnership) {
- mach_msg_type_number_t active_name_count = GetActiveNameCount();
-
- // Making a new SharedMemoryHandle increments the name count.
- SharedMemoryHandle shm(s_memory_size, UnguessableToken::Create());
- ASSERT_TRUE(shm.IsValid());
- EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
-
- // Name count doesn't change when mapping the memory.
- std::unique_ptr<SharedMemory> shared_memory(new SharedMemory(shm, false));
- shared_memory->Map(s_memory_size);
- EXPECT_EQ(active_name_count + 1, GetActiveNameCount());
-
- // Destroying the SharedMemory object frees the resource.
- shared_memory.reset();
- EXPECT_EQ(active_name_count, GetActiveNameCount());
-}
-
-// Tests that the read-only flag works.
-TEST_F(SharedMemoryMacMultiProcessTest, MachReadOnly) {
- std::unique_ptr<SharedMemory> shared_memory(
- CreateSharedMemory(s_memory_size));
-
- SharedMemoryHandle shm2 = shared_memory->handle().Duplicate();
- ASSERT_TRUE(shm2.IsValid());
- SharedMemory shared_memory2(shm2, true);
- shared_memory2.Map(s_memory_size);
- ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), "");
-}
-
-// Tests that duplication of the underlying handle works.
-TEST_F(SharedMemoryMacMultiProcessTest, MachDuplicate) {
- mach_msg_type_number_t active_name_count = GetActiveNameCount();
-
- {
- std::unique_ptr<SharedMemory> shared_memory(
- CreateSharedMemory(s_memory_size));
-
- SharedMemoryHandle shm2 = shared_memory->handle().Duplicate();
- ASSERT_TRUE(shm2.IsValid());
- SharedMemory shared_memory2(shm2, true);
- shared_memory2.Map(s_memory_size);
-
- ASSERT_EQ(0, memcmp(shared_memory->memory(), shared_memory2.memory(),
- s_memory_size));
- }
-
- EXPECT_EQ(active_name_count, GetActiveNameCount());
-}
-
-// Tests that the method GetReadOnlyHandle() creates a memory object that
-// is read only.
-TEST_F(SharedMemoryMacMultiProcessTest, MachReadonly) {
- std::unique_ptr<SharedMemory> shared_memory(
- CreateSharedMemory(s_memory_size));
-
- // Check the protection levels.
- int current_prot, max_prot;
- ASSERT_TRUE(GetProtections(shared_memory->memory(),
- shared_memory->mapped_size(), ¤t_prot,
- &max_prot));
- ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, current_prot);
- ASSERT_EQ(VM_PROT_READ | VM_PROT_WRITE, max_prot);
-
- // Make a new memory object.
- SharedMemoryHandle shm2 = shared_memory->GetReadOnlyHandle();
- ASSERT_TRUE(shm2.IsValid());
- EXPECT_EQ(shared_memory->handle().GetGUID(), shm2.GetGUID());
-
- // Mapping with |readonly| set to |false| should fail.
- SharedMemory shared_memory2(shm2, false);
- shared_memory2.Map(s_memory_size);
- ASSERT_EQ(nullptr, shared_memory2.memory());
-
- // Now trying mapping with |readonly| set to |true|.
- SharedMemory shared_memory3(shm2.Duplicate(), true);
- shared_memory3.Map(s_memory_size);
- ASSERT_NE(nullptr, shared_memory3.memory());
-
- // Check the protection levels.
- ASSERT_TRUE(GetProtections(shared_memory3.memory(),
- shared_memory3.mapped_size(), ¤t_prot,
- &max_prot));
- ASSERT_EQ(VM_PROT_READ, current_prot);
- ASSERT_EQ(VM_PROT_READ, max_prot);
-
- // The memory should still be readonly, since the underlying memory object
- // is readonly.
- ASSERT_DEATH(memset(shared_memory2.memory(), 'b', s_memory_size), "");
-}
-
-// Tests that the method GetReadOnlyHandle() doesn't leak.
-TEST_F(SharedMemoryMacMultiProcessTest, MachReadonlyLeak) {
- mach_msg_type_number_t active_name_count = GetActiveNameCount();
-
- {
- std::unique_ptr<SharedMemory> shared_memory(
- CreateSharedMemory(s_memory_size));
-
- SharedMemoryHandle shm2 = shared_memory->GetReadOnlyHandle();
- ASSERT_TRUE(shm2.IsValid());
-
- // Intentionally map with |readonly| set to |false|.
- SharedMemory shared_memory2(shm2, false);
- shared_memory2.Map(s_memory_size);
- }
-
- EXPECT_EQ(active_name_count, GetActiveNameCount());
-}
-
-} // namespace base
diff --git a/base/memory/shared_memory_region_unittest.cc b/base/memory/shared_memory_region_unittest.cc
deleted file mode 100644
index e917154..0000000
--- a/base/memory/shared_memory_region_unittest.cc
+++ /dev/null
@@ -1,279 +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 <utility>
-
-#include "base/memory/platform_shared_memory_region.h"
-#include "base/memory/read_only_shared_memory_region.h"
-#include "base/memory/unsafe_shared_memory_region.h"
-#include "base/memory/writable_shared_memory_region.h"
-#include "base/sys_info.h"
-#include "base/test/test_shared_memory_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-const size_t kRegionSize = 1024;
-
-bool IsMemoryFilledWithByte(const void* memory, size_t size, char byte) {
- const char* start_ptr = static_cast<const char*>(memory);
- const char* end_ptr = start_ptr + size;
- for (const char* ptr = start_ptr; ptr < end_ptr; ++ptr) {
- if (*ptr != byte)
- return false;
- }
-
- return true;
-}
-
-template <typename SharedMemoryRegionType>
-class SharedMemoryRegionTest : public ::testing::Test {
- public:
- void SetUp() override {
- std::tie(region_, rw_mapping_) =
- CreateMappedRegion<SharedMemoryRegionType>(kRegionSize);
- ASSERT_TRUE(region_.IsValid());
- ASSERT_TRUE(rw_mapping_.IsValid());
- memset(rw_mapping_.memory(), 'G', kRegionSize);
- EXPECT_TRUE(IsMemoryFilledWithByte(rw_mapping_.memory(), kRegionSize, 'G'));
- }
-
- protected:
- SharedMemoryRegionType region_;
- WritableSharedMemoryMapping rw_mapping_;
-};
-
-typedef ::testing::Types<WritableSharedMemoryRegion,
- UnsafeSharedMemoryRegion,
- ReadOnlySharedMemoryRegion>
- AllRegionTypes;
-TYPED_TEST_CASE(SharedMemoryRegionTest, AllRegionTypes);
-
-TYPED_TEST(SharedMemoryRegionTest, NonValidRegion) {
- TypeParam region;
- EXPECT_FALSE(region.IsValid());
- // We shouldn't crash on Map but should return an invalid mapping.
- typename TypeParam::MappingType mapping = region.Map();
- EXPECT_FALSE(mapping.IsValid());
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MoveRegion) {
- TypeParam moved_region = std::move(this->region_);
- EXPECT_FALSE(this->region_.IsValid());
- ASSERT_TRUE(moved_region.IsValid());
-
- // Check that moved region maps correctly.
- typename TypeParam::MappingType mapping = moved_region.Map();
- ASSERT_TRUE(mapping.IsValid());
- EXPECT_NE(this->rw_mapping_.memory(), mapping.memory());
- EXPECT_EQ(memcmp(this->rw_mapping_.memory(), mapping.memory(), kRegionSize),
- 0);
-
- // Verify that the second mapping reflects changes in the first.
- memset(this->rw_mapping_.memory(), '#', kRegionSize);
- EXPECT_EQ(memcmp(this->rw_mapping_.memory(), mapping.memory(), kRegionSize),
- 0);
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MappingValidAfterClose) {
- // Check the mapping is still valid after the region is closed.
- this->region_ = TypeParam();
- EXPECT_FALSE(this->region_.IsValid());
- ASSERT_TRUE(this->rw_mapping_.IsValid());
- EXPECT_TRUE(
- IsMemoryFilledWithByte(this->rw_mapping_.memory(), kRegionSize, 'G'));
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapTwice) {
- // The second mapping is either writable or read-only.
- typename TypeParam::MappingType mapping = this->region_.Map();
- ASSERT_TRUE(mapping.IsValid());
- EXPECT_NE(this->rw_mapping_.memory(), mapping.memory());
- EXPECT_EQ(memcmp(this->rw_mapping_.memory(), mapping.memory(), kRegionSize),
- 0);
-
- // Verify that the second mapping reflects changes in the first.
- memset(this->rw_mapping_.memory(), '#', kRegionSize);
- EXPECT_EQ(memcmp(this->rw_mapping_.memory(), mapping.memory(), kRegionSize),
- 0);
-
- // Close the region and unmap the first memory segment, verify the second
- // still has the right data.
- this->region_ = TypeParam();
- this->rw_mapping_ = WritableSharedMemoryMapping();
- EXPECT_TRUE(IsMemoryFilledWithByte(mapping.memory(), kRegionSize, '#'));
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapUnmapMap) {
- this->rw_mapping_ = WritableSharedMemoryMapping();
-
- typename TypeParam::MappingType mapping = this->region_.Map();
- ASSERT_TRUE(mapping.IsValid());
- EXPECT_TRUE(IsMemoryFilledWithByte(mapping.memory(), kRegionSize, 'G'));
-}
-
-TYPED_TEST(SharedMemoryRegionTest, SerializeAndDeserialize) {
- subtle::PlatformSharedMemoryRegion platform_region =
- TypeParam::TakeHandleForSerialization(std::move(this->region_));
- EXPECT_EQ(platform_region.GetGUID(), this->rw_mapping_.guid());
- TypeParam region = TypeParam::Deserialize(std::move(platform_region));
- EXPECT_TRUE(region.IsValid());
- EXPECT_FALSE(this->region_.IsValid());
- typename TypeParam::MappingType mapping = region.Map();
- ASSERT_TRUE(mapping.IsValid());
- EXPECT_TRUE(IsMemoryFilledWithByte(mapping.memory(), kRegionSize, 'G'));
-
- // Verify that the second mapping reflects changes in the first.
- memset(this->rw_mapping_.memory(), '#', kRegionSize);
- EXPECT_EQ(memcmp(this->rw_mapping_.memory(), mapping.memory(), kRegionSize),
- 0);
-}
-
-// Map() will return addresses which are aligned to the platform page size, this
-// varies from platform to platform though. Since we'd like to advertise a
-// minimum alignment that callers can count on, test for it here.
-TYPED_TEST(SharedMemoryRegionTest, MapMinimumAlignment) {
- EXPECT_EQ(0U,
- reinterpret_cast<uintptr_t>(this->rw_mapping_.memory()) &
- (subtle::PlatformSharedMemoryRegion::kMapMinimumAlignment - 1));
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapSize) {
- EXPECT_EQ(this->rw_mapping_.size(), kRegionSize);
- EXPECT_GE(this->rw_mapping_.mapped_size(), kRegionSize);
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapGranularity) {
- EXPECT_LT(this->rw_mapping_.mapped_size(),
- kRegionSize + SysInfo::VMAllocationGranularity());
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapAt) {
- const size_t kPageSize = SysInfo::VMAllocationGranularity();
- ASSERT_TRUE(kPageSize >= sizeof(uint32_t));
- ASSERT_EQ(kPageSize % sizeof(uint32_t), 0U);
- const size_t kDataSize = kPageSize * 2;
- const size_t kCount = kDataSize / sizeof(uint32_t);
-
- TypeParam region;
- WritableSharedMemoryMapping rw_mapping;
- std::tie(region, rw_mapping) = CreateMappedRegion<TypeParam>(kDataSize);
- ASSERT_TRUE(region.IsValid());
- ASSERT_TRUE(rw_mapping.IsValid());
- uint32_t* ptr = static_cast<uint32_t*>(rw_mapping.memory());
-
- for (size_t i = 0; i < kCount; ++i)
- ptr[i] = i;
-
- rw_mapping = WritableSharedMemoryMapping();
- off_t bytes_offset = kPageSize;
- typename TypeParam::MappingType mapping =
- region.MapAt(bytes_offset, kDataSize - bytes_offset);
- ASSERT_TRUE(mapping.IsValid());
-
- off_t int_offset = bytes_offset / sizeof(uint32_t);
- const uint32_t* ptr2 = static_cast<const uint32_t*>(mapping.memory());
- for (size_t i = int_offset; i < kCount; ++i) {
- EXPECT_EQ(ptr2[i - int_offset], i);
- }
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapAtNotAlignedOffsetFails) {
- const size_t kDataSize = SysInfo::VMAllocationGranularity();
-
- TypeParam region;
- WritableSharedMemoryMapping rw_mapping;
- std::tie(region, rw_mapping) = CreateMappedRegion<TypeParam>(kDataSize);
- ASSERT_TRUE(region.IsValid());
- ASSERT_TRUE(rw_mapping.IsValid());
- off_t offset = kDataSize / 2;
- typename TypeParam::MappingType mapping =
- region.MapAt(offset, kDataSize - offset);
- EXPECT_FALSE(mapping.IsValid());
-}
-
-TYPED_TEST(SharedMemoryRegionTest, MapMoreBytesThanRegionSizeFails) {
- size_t region_real_size = this->region_.GetSize();
- typename TypeParam::MappingType mapping =
- this->region_.MapAt(0, region_real_size + 1);
- EXPECT_FALSE(mapping.IsValid());
-}
-
-template <typename DuplicatableSharedMemoryRegion>
-class DuplicatableSharedMemoryRegionTest
- : public SharedMemoryRegionTest<DuplicatableSharedMemoryRegion> {};
-
-typedef ::testing::Types<UnsafeSharedMemoryRegion, ReadOnlySharedMemoryRegion>
- DuplicatableRegionTypes;
-TYPED_TEST_CASE(DuplicatableSharedMemoryRegionTest, DuplicatableRegionTypes);
-
-TYPED_TEST(DuplicatableSharedMemoryRegionTest, Duplicate) {
- TypeParam dup_region = this->region_.Duplicate();
- typename TypeParam::MappingType mapping = dup_region.Map();
- ASSERT_TRUE(mapping.IsValid());
- EXPECT_NE(this->rw_mapping_.memory(), mapping.memory());
- EXPECT_EQ(this->rw_mapping_.guid(), mapping.guid());
- EXPECT_TRUE(IsMemoryFilledWithByte(mapping.memory(), kRegionSize, 'G'));
-}
-
-class ReadOnlySharedMemoryRegionTest : public ::testing::Test {
- public:
- ReadOnlySharedMemoryRegion GetInitiallyReadOnlyRegion(size_t size) {
- MappedReadOnlyRegion mapped_region =
- ReadOnlySharedMemoryRegion::Create(size);
- ReadOnlySharedMemoryRegion region = std::move(mapped_region.region);
- return region;
- }
-
- ReadOnlySharedMemoryRegion GetConvertedToReadOnlyRegion(size_t size) {
- WritableSharedMemoryRegion region =
- WritableSharedMemoryRegion::Create(kRegionSize);
- ReadOnlySharedMemoryRegion ro_region =
- WritableSharedMemoryRegion::ConvertToReadOnly(std::move(region));
- return ro_region;
- }
-};
-
-TEST_F(ReadOnlySharedMemoryRegionTest,
- InitiallyReadOnlyRegionCannotBeMappedAsWritable) {
- ReadOnlySharedMemoryRegion region = GetInitiallyReadOnlyRegion(kRegionSize);
- ASSERT_TRUE(region.IsValid());
-
- EXPECT_TRUE(CheckReadOnlyPlatformSharedMemoryRegionForTesting(
- ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
- std::move(region))));
-}
-
-TEST_F(ReadOnlySharedMemoryRegionTest,
- ConvertedToReadOnlyRegionCannotBeMappedAsWritable) {
- ReadOnlySharedMemoryRegion region = GetConvertedToReadOnlyRegion(kRegionSize);
- ASSERT_TRUE(region.IsValid());
-
- EXPECT_TRUE(CheckReadOnlyPlatformSharedMemoryRegionForTesting(
- ReadOnlySharedMemoryRegion::TakeHandleForSerialization(
- std::move(region))));
-}
-
-TEST_F(ReadOnlySharedMemoryRegionTest,
- InitiallyReadOnlyRegionProducedMappingWriteDeathTest) {
- ReadOnlySharedMemoryRegion region = GetInitiallyReadOnlyRegion(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- ReadOnlySharedMemoryMapping mapping = region.Map();
- ASSERT_TRUE(mapping.IsValid());
- void* memory_ptr = const_cast<void*>(mapping.memory());
- EXPECT_DEATH_IF_SUPPORTED(memset(memory_ptr, 'G', kRegionSize), "");
-}
-
-TEST_F(ReadOnlySharedMemoryRegionTest,
- ConvertedToReadOnlyRegionProducedMappingWriteDeathTest) {
- ReadOnlySharedMemoryRegion region = GetConvertedToReadOnlyRegion(kRegionSize);
- ASSERT_TRUE(region.IsValid());
- ReadOnlySharedMemoryMapping mapping = region.Map();
- ASSERT_TRUE(mapping.IsValid());
- void* memory_ptr = const_cast<void*>(mapping.memory());
- EXPECT_DEATH_IF_SUPPORTED(memset(memory_ptr, 'G', kRegionSize), "");
-}
-
-} // namespace base
diff --git a/base/memory/shared_memory_unittest.cc b/base/memory/shared_memory_unittest.cc
deleted file mode 100644
index c4c21c4..0000000
--- a/base/memory/shared_memory_unittest.cc
+++ /dev/null
@@ -1,965 +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/memory/shared_memory.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-
-#include "base/atomicops.h"
-#include "base/base_switches.h"
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/shared_memory_handle.h"
-#include "base/process/kill.h"
-#include "base/rand_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/sys_info.h"
-#include "base/test/multiprocess_test.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "base/unguessable_token.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-#if defined(OS_ANDROID)
-#include "base/callback.h"
-#endif
-
-#if defined(OS_POSIX)
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-#endif
-
-#if defined(OS_LINUX)
-#include <sys/syscall.h>
-#endif
-
-#if defined(OS_WIN)
-#include "base/win/scoped_handle.h"
-#endif
-
-#if defined(OS_FUCHSIA)
-#include <zircon/process.h>
-#include <zircon/syscalls.h>
-#include "base/fuchsia/scoped_zx_handle.h"
-#endif
-
-namespace base {
-
-namespace {
-
-#if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-// Each thread will open the shared memory. Each thread will take a different 4
-// byte int pointer, and keep changing it, with some small pauses in between.
-// Verify that each thread's value in the shared memory is always correct.
-class MultipleThreadMain : public PlatformThread::Delegate {
- public:
- explicit MultipleThreadMain(int16_t id) : id_(id) {}
- ~MultipleThreadMain() override = default;
-
- static void CleanUp() {
- SharedMemory memory;
- memory.Delete(s_test_name_);
- }
-
- // PlatformThread::Delegate interface.
- void ThreadMain() override {
- const uint32_t kDataSize = 1024;
- SharedMemory memory;
- bool rv = memory.CreateNamedDeprecated(s_test_name_, true, kDataSize);
- EXPECT_TRUE(rv);
- rv = memory.Map(kDataSize);
- EXPECT_TRUE(rv);
- int* ptr = static_cast<int*>(memory.memory()) + id_;
- EXPECT_EQ(0, *ptr);
-
- for (int idx = 0; idx < 100; idx++) {
- *ptr = idx;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(1));
- EXPECT_EQ(*ptr, idx);
- }
- // Reset back to 0 for the next test that uses the same name.
- *ptr = 0;
-
- memory.Close();
- }
-
- private:
- int16_t id_;
-
- static const char s_test_name_[];
-
- DISALLOW_COPY_AND_ASSIGN(MultipleThreadMain);
-};
-
-const char MultipleThreadMain::s_test_name_[] =
- "SharedMemoryOpenThreadTest";
-#endif // !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-
-enum class Mode {
- Default,
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- DisableDevShm = 1,
-#endif
-};
-
-class SharedMemoryTest : public ::testing::TestWithParam<Mode> {
- public:
- void SetUp() override {
- switch (GetParam()) {
- case Mode::Default:
- break;
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- case Mode::DisableDevShm:
- CommandLine* cmdline = CommandLine::ForCurrentProcess();
- cmdline->AppendSwitch(switches::kDisableDevShmUsage);
- break;
-#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
- }
- }
-};
-
-} // namespace
-
-// Android/Mac/Fuchsia doesn't support SharedMemory::Open/Delete/
-// CreateNamedDeprecated(openExisting=true)
-#if !defined(OS_ANDROID) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-
-TEST_P(SharedMemoryTest, OpenClose) {
- const uint32_t kDataSize = 1024;
- std::string test_name = "SharedMemoryOpenCloseTest";
-
- // Open two handles to a memory segment, confirm that they are mapped
- // separately yet point to the same space.
- SharedMemory memory1;
- bool rv = memory1.Delete(test_name);
- EXPECT_TRUE(rv);
- rv = memory1.Delete(test_name);
- EXPECT_TRUE(rv);
- rv = memory1.Open(test_name, false);
- EXPECT_FALSE(rv);
- rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
- EXPECT_TRUE(rv);
- rv = memory1.Map(kDataSize);
- EXPECT_TRUE(rv);
- SharedMemory memory2;
- rv = memory2.Open(test_name, false);
- EXPECT_TRUE(rv);
- rv = memory2.Map(kDataSize);
- EXPECT_TRUE(rv);
- EXPECT_NE(memory1.memory(), memory2.memory()); // Compare the pointers.
-
- // Make sure we don't segfault. (it actually happened!)
- ASSERT_NE(memory1.memory(), static_cast<void*>(nullptr));
- ASSERT_NE(memory2.memory(), static_cast<void*>(nullptr));
-
- // Write data to the first memory segment, verify contents of second.
- memset(memory1.memory(), '1', kDataSize);
- EXPECT_EQ(memcmp(memory1.memory(), memory2.memory(), kDataSize), 0);
-
- // Close the first memory segment, and verify the second has the right data.
- memory1.Close();
- char* start_ptr = static_cast<char*>(memory2.memory());
- char* end_ptr = start_ptr + kDataSize;
- for (char* ptr = start_ptr; ptr < end_ptr; ptr++)
- EXPECT_EQ(*ptr, '1');
-
- // Close the second memory segment.
- memory2.Close();
-
- rv = memory1.Delete(test_name);
- EXPECT_TRUE(rv);
- rv = memory2.Delete(test_name);
- EXPECT_TRUE(rv);
-}
-
-TEST_P(SharedMemoryTest, OpenExclusive) {
- const uint32_t kDataSize = 1024;
- const uint32_t kDataSize2 = 2048;
- std::ostringstream test_name_stream;
- test_name_stream << "SharedMemoryOpenExclusiveTest."
- << Time::Now().ToDoubleT();
- std::string test_name = test_name_stream.str();
-
- // Open two handles to a memory segment and check that
- // open_existing_deprecated works as expected.
- SharedMemory memory1;
- bool rv = memory1.CreateNamedDeprecated(test_name, false, kDataSize);
- EXPECT_TRUE(rv);
-
- // Memory1 knows it's size because it created it.
- EXPECT_EQ(memory1.requested_size(), kDataSize);
-
- rv = memory1.Map(kDataSize);
- EXPECT_TRUE(rv);
-
- // The mapped memory1 must be at least the size we asked for.
- EXPECT_GE(memory1.mapped_size(), kDataSize);
-
- // The mapped memory1 shouldn't exceed rounding for allocation granularity.
- EXPECT_LT(memory1.mapped_size(),
- kDataSize + SysInfo::VMAllocationGranularity());
-
- memset(memory1.memory(), 'G', kDataSize);
-
- SharedMemory memory2;
- // Should not be able to create if openExisting is false.
- rv = memory2.CreateNamedDeprecated(test_name, false, kDataSize2);
- EXPECT_FALSE(rv);
-
- // Should be able to create with openExisting true.
- rv = memory2.CreateNamedDeprecated(test_name, true, kDataSize2);
- EXPECT_TRUE(rv);
-
- // Memory2 shouldn't know the size because we didn't create it.
- EXPECT_EQ(memory2.requested_size(), 0U);
-
- // We should be able to map the original size.
- rv = memory2.Map(kDataSize);
- EXPECT_TRUE(rv);
-
- // The mapped memory2 must be at least the size of the original.
- EXPECT_GE(memory2.mapped_size(), kDataSize);
-
- // The mapped memory2 shouldn't exceed rounding for allocation granularity.
- EXPECT_LT(memory2.mapped_size(),
- kDataSize2 + SysInfo::VMAllocationGranularity());
-
- // Verify that opening memory2 didn't truncate or delete memory 1.
- char* start_ptr = static_cast<char*>(memory2.memory());
- char* end_ptr = start_ptr + kDataSize;
- for (char* ptr = start_ptr; ptr < end_ptr; ptr++) {
- EXPECT_EQ(*ptr, 'G');
- }
-
- memory1.Close();
- memory2.Close();
-
- rv = memory1.Delete(test_name);
- EXPECT_TRUE(rv);
-}
-#endif // !defined(OS_ANDROID) && !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-
-// Check that memory is still mapped after its closed.
-TEST_P(SharedMemoryTest, CloseNoUnmap) {
- const size_t kDataSize = 4096;
-
- SharedMemory memory;
- ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
- char* ptr = static_cast<char*>(memory.memory());
- ASSERT_NE(ptr, static_cast<void*>(nullptr));
- memset(ptr, 'G', kDataSize);
-
- memory.Close();
-
- EXPECT_EQ(ptr, memory.memory());
- EXPECT_TRUE(!memory.handle().IsValid());
-
- for (size_t i = 0; i < kDataSize; i++) {
- EXPECT_EQ('G', ptr[i]);
- }
-
- memory.Unmap();
- EXPECT_EQ(nullptr, memory.memory());
-}
-
-#if !defined(OS_MACOSX) && !defined(OS_FUCHSIA)
-// Create a set of N threads to each open a shared memory segment and write to
-// it. Verify that they are always reading/writing consistent data.
-TEST_P(SharedMemoryTest, MultipleThreads) {
- const int kNumThreads = 5;
-
- MultipleThreadMain::CleanUp();
- // On POSIX we have a problem when 2 threads try to create the shmem
- // (a file) at exactly the same time, since create both creates the
- // file and zerofills it. We solve the problem for this unit test
- // (make it not flaky) by starting with 1 thread, then
- // intentionally don't clean up its shmem before running with
- // kNumThreads.
-
- int threadcounts[] = { 1, kNumThreads };
- for (size_t i = 0; i < arraysize(threadcounts); i++) {
- int numthreads = threadcounts[i];
- std::unique_ptr<PlatformThreadHandle[]> thread_handles;
- std::unique_ptr<MultipleThreadMain* []> thread_delegates;
-
- thread_handles.reset(new PlatformThreadHandle[numthreads]);
- thread_delegates.reset(new MultipleThreadMain*[numthreads]);
-
- // Spawn the threads.
- for (int16_t index = 0; index < numthreads; index++) {
- PlatformThreadHandle pth;
- thread_delegates[index] = new MultipleThreadMain(index);
- EXPECT_TRUE(PlatformThread::Create(0, thread_delegates[index], &pth));
- thread_handles[index] = pth;
- }
-
- // Wait for the threads to finish.
- for (int index = 0; index < numthreads; index++) {
- PlatformThread::Join(thread_handles[index]);
- delete thread_delegates[index];
- }
- }
- MultipleThreadMain::CleanUp();
-}
-#endif
-
-// Allocate private (unique) shared memory with an empty string for a
-// name. Make sure several of them don't point to the same thing as
-// we might expect if the names are equal.
-TEST_P(SharedMemoryTest, AnonymousPrivate) {
- int i, j;
- int count = 4;
- bool rv;
- const uint32_t kDataSize = 8192;
-
- std::unique_ptr<SharedMemory[]> memories(new SharedMemory[count]);
- std::unique_ptr<int* []> pointers(new int*[count]);
- ASSERT_TRUE(memories.get());
- ASSERT_TRUE(pointers.get());
-
- for (i = 0; i < count; i++) {
- rv = memories[i].CreateAndMapAnonymous(kDataSize);
- EXPECT_TRUE(rv);
- int* ptr = static_cast<int*>(memories[i].memory());
- EXPECT_TRUE(ptr);
- pointers[i] = ptr;
- }
-
- for (i = 0; i < count; i++) {
- // zero out the first int in each except for i; for that one, make it 100.
- for (j = 0; j < count; j++) {
- if (i == j)
- pointers[j][0] = 100;
- else
- pointers[j][0] = 0;
- }
- // make sure there is no bleeding of the 100 into the other pointers
- for (j = 0; j < count; j++) {
- if (i == j)
- EXPECT_EQ(100, pointers[j][0]);
- else
- EXPECT_EQ(0, pointers[j][0]);
- }
- }
-
- for (int i = 0; i < count; i++) {
- memories[i].Close();
- }
-}
-
-TEST_P(SharedMemoryTest, GetReadOnlyHandle) {
- StringPiece contents = "Hello World";
-
- SharedMemory writable_shmem;
- SharedMemoryCreateOptions options;
- options.size = contents.size();
- options.share_read_only = true;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // The Mach functionality is tested in shared_memory_mac_unittest.cc.
- options.type = SharedMemoryHandle::POSIX;
-#endif
- ASSERT_TRUE(writable_shmem.Create(options));
- ASSERT_TRUE(writable_shmem.Map(options.size));
- memcpy(writable_shmem.memory(), contents.data(), contents.size());
- EXPECT_TRUE(writable_shmem.Unmap());
-
- SharedMemoryHandle readonly_handle = writable_shmem.GetReadOnlyHandle();
- EXPECT_EQ(writable_shmem.handle().GetGUID(), readonly_handle.GetGUID());
- EXPECT_EQ(writable_shmem.handle().GetSize(), readonly_handle.GetSize());
- ASSERT_TRUE(readonly_handle.IsValid());
- SharedMemory readonly_shmem(readonly_handle, /*readonly=*/true);
-
- ASSERT_TRUE(readonly_shmem.Map(contents.size()));
- EXPECT_EQ(contents,
- StringPiece(static_cast<const char*>(readonly_shmem.memory()),
- contents.size()));
- EXPECT_TRUE(readonly_shmem.Unmap());
-
-#if defined(OS_ANDROID)
- // On Android, mapping a region through a read-only descriptor makes the
- // region read-only. Any writable mapping attempt should fail.
- ASSERT_FALSE(writable_shmem.Map(contents.size()));
-#else
- // Make sure the writable instance is still writable.
- ASSERT_TRUE(writable_shmem.Map(contents.size()));
- StringPiece new_contents = "Goodbye";
- memcpy(writable_shmem.memory(), new_contents.data(), new_contents.size());
- EXPECT_EQ(new_contents,
- StringPiece(static_cast<const char*>(writable_shmem.memory()),
- new_contents.size()));
-#endif
-
- // We'd like to check that if we send the read-only segment to another
- // process, then that other process can't reopen it read/write. (Since that
- // would be a security hole.) Setting up multiple processes is hard in a
- // unittest, so this test checks that the *current* process can't reopen the
- // segment read/write. I think the test here is stronger than we actually
- // care about, but there's a remote possibility that sending a file over a
- // pipe would transform it into read/write.
- SharedMemoryHandle handle = readonly_shmem.handle();
-
-#if defined(OS_ANDROID)
- // The "read-only" handle is still writable on Android:
- // http://crbug.com/320865
- (void)handle;
-#elif defined(OS_FUCHSIA)
- uintptr_t addr;
- EXPECT_NE(ZX_OK, zx_vmar_map(zx_vmar_root_self(), 0, handle.GetHandle(), 0,
- contents.size(), ZX_VM_FLAG_PERM_WRITE, &addr))
- << "Shouldn't be able to map as writable.";
-
- ScopedZxHandle duped_handle;
- EXPECT_NE(ZX_OK, zx_handle_duplicate(handle.GetHandle(), ZX_RIGHT_WRITE,
- duped_handle.receive()))
- << "Shouldn't be able to duplicate the handle into a writable one.";
-
- EXPECT_EQ(ZX_OK, zx_handle_duplicate(handle.GetHandle(), ZX_RIGHT_READ,
- duped_handle.receive()))
- << "Should be able to duplicate the handle into a readable one.";
-#elif defined(OS_POSIX)
- int handle_fd = SharedMemory::GetFdFromSharedMemoryHandle(handle);
- EXPECT_EQ(O_RDONLY, fcntl(handle_fd, F_GETFL) & O_ACCMODE)
- << "The descriptor itself should be read-only.";
-
- errno = 0;
- void* writable = mmap(nullptr, contents.size(), PROT_READ | PROT_WRITE,
- MAP_SHARED, handle_fd, 0);
- int mmap_errno = errno;
- EXPECT_EQ(MAP_FAILED, writable)
- << "It shouldn't be possible to re-mmap the descriptor writable.";
- EXPECT_EQ(EACCES, mmap_errno) << strerror(mmap_errno);
- if (writable != MAP_FAILED)
- EXPECT_EQ(0, munmap(writable, readonly_shmem.mapped_size()));
-
-#elif defined(OS_WIN)
- EXPECT_EQ(NULL, MapViewOfFile(handle.GetHandle(), FILE_MAP_WRITE, 0, 0, 0))
- << "Shouldn't be able to map memory writable.";
-
- HANDLE temp_handle;
- BOOL rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
- GetCurrentProcess(), &temp_handle,
- FILE_MAP_ALL_ACCESS, false, 0);
- EXPECT_EQ(FALSE, rv)
- << "Shouldn't be able to duplicate the handle into a writable one.";
- if (rv)
- win::ScopedHandle writable_handle(temp_handle);
- rv = ::DuplicateHandle(GetCurrentProcess(), handle.GetHandle(),
- GetCurrentProcess(), &temp_handle, FILE_MAP_READ,
- false, 0);
- EXPECT_EQ(TRUE, rv)
- << "Should be able to duplicate the handle into a readable one.";
- if (rv)
- win::ScopedHandle writable_handle(temp_handle);
-#else
-#error Unexpected platform; write a test that tries to make 'handle' writable.
-#endif // defined(OS_POSIX) || defined(OS_WIN)
-}
-
-TEST_P(SharedMemoryTest, ShareToSelf) {
- StringPiece contents = "Hello World";
-
- SharedMemory shmem;
- ASSERT_TRUE(shmem.CreateAndMapAnonymous(contents.size()));
- memcpy(shmem.memory(), contents.data(), contents.size());
- EXPECT_TRUE(shmem.Unmap());
-
- SharedMemoryHandle shared_handle = shmem.handle().Duplicate();
- ASSERT_TRUE(shared_handle.IsValid());
- EXPECT_TRUE(shared_handle.OwnershipPassesToIPC());
- EXPECT_EQ(shared_handle.GetGUID(), shmem.handle().GetGUID());
- EXPECT_EQ(shared_handle.GetSize(), shmem.handle().GetSize());
- SharedMemory shared(shared_handle, /*readonly=*/false);
-
- ASSERT_TRUE(shared.Map(contents.size()));
- EXPECT_EQ(
- contents,
- StringPiece(static_cast<const char*>(shared.memory()), contents.size()));
-
- shared_handle = shmem.handle().Duplicate();
- ASSERT_TRUE(shared_handle.IsValid());
- ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
- SharedMemory readonly(shared_handle, /*readonly=*/true);
-
- ASSERT_TRUE(readonly.Map(contents.size()));
- EXPECT_EQ(contents,
- StringPiece(static_cast<const char*>(readonly.memory()),
- contents.size()));
-}
-
-TEST_P(SharedMemoryTest, ShareWithMultipleInstances) {
- static const StringPiece kContents = "Hello World";
-
- SharedMemory shmem;
- ASSERT_TRUE(shmem.CreateAndMapAnonymous(kContents.size()));
- // We do not need to unmap |shmem| to let |shared| map.
- const StringPiece shmem_contents(static_cast<const char*>(shmem.memory()),
- shmem.requested_size());
-
- SharedMemoryHandle shared_handle = shmem.handle().Duplicate();
- ASSERT_TRUE(shared_handle.IsValid());
- SharedMemory shared(shared_handle, /*readonly=*/false);
- ASSERT_TRUE(shared.Map(kContents.size()));
- // The underlying shared memory is created by |shmem|, so both
- // |shared|.requested_size() and |readonly|.requested_size() are zero.
- ASSERT_EQ(0U, shared.requested_size());
- const StringPiece shared_contents(static_cast<const char*>(shared.memory()),
- shmem.requested_size());
-
- shared_handle = shmem.handle().Duplicate();
- ASSERT_TRUE(shared_handle.IsValid());
- ASSERT_TRUE(shared_handle.OwnershipPassesToIPC());
- SharedMemory readonly(shared_handle, /*readonly=*/true);
- ASSERT_TRUE(readonly.Map(kContents.size()));
- ASSERT_EQ(0U, readonly.requested_size());
- const StringPiece readonly_contents(
- static_cast<const char*>(readonly.memory()),
- shmem.requested_size());
-
- // |shmem| should be able to update the content.
- memcpy(shmem.memory(), kContents.data(), kContents.size());
-
- ASSERT_EQ(kContents, shmem_contents);
- ASSERT_EQ(kContents, shared_contents);
- ASSERT_EQ(kContents, readonly_contents);
-
- // |shared| should also be able to update the content.
- memcpy(shared.memory(), ToLowerASCII(kContents).c_str(), kContents.size());
-
- ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), shmem_contents);
- ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), shared_contents);
- ASSERT_EQ(StringPiece(ToLowerASCII(kContents)), readonly_contents);
-}
-
-TEST_P(SharedMemoryTest, MapAt) {
- ASSERT_TRUE(SysInfo::VMAllocationGranularity() >= sizeof(uint32_t));
- const size_t kCount = SysInfo::VMAllocationGranularity();
- const size_t kDataSize = kCount * sizeof(uint32_t);
-
- SharedMemory memory;
- ASSERT_TRUE(memory.CreateAndMapAnonymous(kDataSize));
- uint32_t* ptr = static_cast<uint32_t*>(memory.memory());
- ASSERT_NE(ptr, static_cast<void*>(nullptr));
-
- for (size_t i = 0; i < kCount; ++i) {
- ptr[i] = i;
- }
-
- memory.Unmap();
-
- off_t offset = SysInfo::VMAllocationGranularity();
- ASSERT_TRUE(memory.MapAt(offset, kDataSize - offset));
- offset /= sizeof(uint32_t);
- ptr = static_cast<uint32_t*>(memory.memory());
- ASSERT_NE(ptr, static_cast<void*>(nullptr));
- for (size_t i = offset; i < kCount; ++i) {
- EXPECT_EQ(ptr[i - offset], i);
- }
-}
-
-TEST_P(SharedMemoryTest, MapTwice) {
- const uint32_t kDataSize = 1024;
- SharedMemory memory;
- bool rv = memory.CreateAndMapAnonymous(kDataSize);
- EXPECT_TRUE(rv);
-
- void* old_address = memory.memory();
-
- rv = memory.Map(kDataSize);
- EXPECT_FALSE(rv);
- EXPECT_EQ(old_address, memory.memory());
-}
-
-#if defined(OS_POSIX)
-// This test is not applicable for iOS (crbug.com/399384).
-#if !defined(OS_IOS)
-// Create a shared memory object, mmap it, and mprotect it to PROT_EXEC.
-TEST_P(SharedMemoryTest, AnonymousExecutable) {
- const uint32_t kTestSize = 1 << 16;
-
- SharedMemory shared_memory;
- SharedMemoryCreateOptions options;
- options.size = kTestSize;
- options.executable = true;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // The Mach functionality is tested in shared_memory_mac_unittest.cc.
- options.type = SharedMemoryHandle::POSIX;
-#endif
-
- EXPECT_TRUE(shared_memory.Create(options));
- EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
-
- EXPECT_EQ(0, mprotect(shared_memory.memory(), shared_memory.requested_size(),
- PROT_READ | PROT_EXEC));
-}
-#endif // !defined(OS_IOS)
-
-#if defined(OS_ANDROID)
-// This test is restricted to Android since there is no way on other platforms
-// to guarantee that a region can never be mapped with PROT_EXEC. E.g. on
-// Linux, anonymous shared regions come from /dev/shm which can be mounted
-// without 'noexec'. In this case, anything can perform an mprotect() to
-// change the protection mask of a given page.
-TEST(SharedMemoryTest, AnonymousIsNotExecutableByDefault) {
- const uint32_t kTestSize = 1 << 16;
-
- SharedMemory shared_memory;
- SharedMemoryCreateOptions options;
- options.size = kTestSize;
-
- EXPECT_TRUE(shared_memory.Create(options));
- EXPECT_TRUE(shared_memory.Map(shared_memory.requested_size()));
-
- errno = 0;
- EXPECT_EQ(-1, mprotect(shared_memory.memory(), shared_memory.requested_size(),
- PROT_READ | PROT_EXEC));
- EXPECT_EQ(EACCES, errno);
-}
-#endif // OS_ANDROID
-
-// Android supports a different permission model than POSIX for its "ashmem"
-// shared memory implementation. So the tests about file permissions are not
-// included on Android. Fuchsia does not use a file-backed shared memory
-// implementation.
-
-#if !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-
-// Set a umask and restore the old mask on destruction.
-class ScopedUmaskSetter {
- public:
- explicit ScopedUmaskSetter(mode_t target_mask) {
- old_umask_ = umask(target_mask);
- }
- ~ScopedUmaskSetter() { umask(old_umask_); }
- private:
- mode_t old_umask_;
- DISALLOW_IMPLICIT_CONSTRUCTORS(ScopedUmaskSetter);
-};
-
-// Create a shared memory object, check its permissions.
-TEST_P(SharedMemoryTest, FilePermissionsAnonymous) {
- const uint32_t kTestSize = 1 << 8;
-
- SharedMemory shared_memory;
- SharedMemoryCreateOptions options;
- options.size = kTestSize;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // The Mach functionality is tested in shared_memory_mac_unittest.cc.
- options.type = SharedMemoryHandle::POSIX;
-#endif
- // Set a file mode creation mask that gives all permissions.
- ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
-
- EXPECT_TRUE(shared_memory.Create(options));
-
- int shm_fd =
- SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
- struct stat shm_stat;
- EXPECT_EQ(0, fstat(shm_fd, &shm_stat));
- // Neither the group, nor others should be able to read the shared memory
- // file.
- EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
- EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
-}
-
-// Create a shared memory object, check its permissions.
-TEST_P(SharedMemoryTest, FilePermissionsNamed) {
- const uint32_t kTestSize = 1 << 8;
-
- SharedMemory shared_memory;
- SharedMemoryCreateOptions options;
- options.size = kTestSize;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // The Mach functionality is tested in shared_memory_mac_unittest.cc.
- options.type = SharedMemoryHandle::POSIX;
-#endif
-
- // Set a file mode creation mask that gives all permissions.
- ScopedUmaskSetter permissive_mask(S_IWGRP | S_IWOTH);
-
- EXPECT_TRUE(shared_memory.Create(options));
-
- int fd = SharedMemory::GetFdFromSharedMemoryHandle(shared_memory.handle());
- struct stat shm_stat;
- EXPECT_EQ(0, fstat(fd, &shm_stat));
- // Neither the group, nor others should have been able to open the shared
- // memory file while its name existed.
- EXPECT_FALSE(shm_stat.st_mode & S_IRWXO);
- EXPECT_FALSE(shm_stat.st_mode & S_IRWXG);
-}
-#endif // !defined(OS_ANDROID) && !defined(OS_FUCHSIA)
-
-#endif // defined(OS_POSIX)
-
-// Map() will return addresses which are aligned to the platform page size, this
-// varies from platform to platform though. Since we'd like to advertise a
-// minimum alignment that callers can count on, test for it here.
-TEST_P(SharedMemoryTest, MapMinimumAlignment) {
- static const int kDataSize = 8192;
-
- SharedMemory shared_memory;
- ASSERT_TRUE(shared_memory.CreateAndMapAnonymous(kDataSize));
- EXPECT_EQ(0U, reinterpret_cast<uintptr_t>(
- shared_memory.memory()) & (SharedMemory::MAP_MINIMUM_ALIGNMENT - 1));
- shared_memory.Close();
-}
-
-#if defined(OS_WIN)
-TEST_P(SharedMemoryTest, UnsafeImageSection) {
- const char kTestSectionName[] = "UnsafeImageSection";
- wchar_t path[MAX_PATH];
- EXPECT_GT(::GetModuleFileName(nullptr, path, arraysize(path)), 0U);
-
- // Map the current executable image to save us creating a new PE file on disk.
- base::win::ScopedHandle file_handle(::CreateFile(
- path, GENERIC_READ, FILE_SHARE_READ, nullptr, OPEN_EXISTING, 0, nullptr));
- EXPECT_TRUE(file_handle.IsValid());
- base::win::ScopedHandle section_handle(
- ::CreateFileMappingA(file_handle.Get(), nullptr,
- PAGE_READONLY | SEC_IMAGE, 0, 0, kTestSectionName));
- EXPECT_TRUE(section_handle.IsValid());
-
- // Check direct opening by name, from handle and duplicated from handle.
- SharedMemory shared_memory_open;
- EXPECT_TRUE(shared_memory_open.Open(kTestSectionName, true));
- EXPECT_FALSE(shared_memory_open.Map(1));
- EXPECT_EQ(nullptr, shared_memory_open.memory());
-
- SharedMemory shared_memory_handle_local(
- SharedMemoryHandle(section_handle.Take(), 1, UnguessableToken::Create()),
- true);
- EXPECT_FALSE(shared_memory_handle_local.Map(1));
- EXPECT_EQ(nullptr, shared_memory_handle_local.memory());
-
- // Check that a handle without SECTION_QUERY also can't be mapped as it can't
- // be checked.
- SharedMemory shared_memory_handle_dummy;
- SharedMemoryCreateOptions options;
- options.size = 0x1000;
- EXPECT_TRUE(shared_memory_handle_dummy.Create(options));
- HANDLE handle_no_query;
- EXPECT_TRUE(::DuplicateHandle(
- ::GetCurrentProcess(), shared_memory_handle_dummy.handle().GetHandle(),
- ::GetCurrentProcess(), &handle_no_query, FILE_MAP_READ, FALSE, 0));
- SharedMemory shared_memory_handle_no_query(
- SharedMemoryHandle(handle_no_query, options.size,
- UnguessableToken::Create()),
- true);
- EXPECT_FALSE(shared_memory_handle_no_query.Map(1));
- EXPECT_EQ(nullptr, shared_memory_handle_no_query.memory());
-}
-#endif // defined(OS_WIN)
-
-// iOS does not allow multiple processes.
-// Android ashmem does not support named shared memory.
-// Fuchsia SharedMemory does not support named shared memory.
-// Mac SharedMemory does not support named shared memory. crbug.com/345734
-#if !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) && \
- !defined(OS_FUCHSIA)
-// On POSIX it is especially important we test shmem across processes,
-// not just across threads. But the test is enabled on all platforms.
-class SharedMemoryProcessTest : public MultiProcessTest {
- public:
- static void CleanUp() {
- SharedMemory memory;
- memory.Delete(s_test_name_);
- }
-
- static int TaskTestMain() {
- int errors = 0;
- SharedMemory memory;
- bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
- EXPECT_TRUE(rv);
- if (rv != true)
- errors++;
- rv = memory.Map(s_data_size_);
- EXPECT_TRUE(rv);
- if (rv != true)
- errors++;
- int* ptr = static_cast<int*>(memory.memory());
-
- // This runs concurrently in multiple processes. Writes need to be atomic.
- subtle::Barrier_AtomicIncrement(ptr, 1);
- memory.Close();
- return errors;
- }
-
- static const char s_test_name_[];
- static const uint32_t s_data_size_;
-};
-
-const char SharedMemoryProcessTest::s_test_name_[] = "MPMem";
-const uint32_t SharedMemoryProcessTest::s_data_size_ = 1024;
-
-TEST_F(SharedMemoryProcessTest, SharedMemoryAcrossProcesses) {
- const int kNumTasks = 5;
-
- SharedMemoryProcessTest::CleanUp();
-
- // Create a shared memory region. Set the first word to 0.
- SharedMemory memory;
- bool rv = memory.CreateNamedDeprecated(s_test_name_, true, s_data_size_);
- ASSERT_TRUE(rv);
- rv = memory.Map(s_data_size_);
- ASSERT_TRUE(rv);
- int* ptr = static_cast<int*>(memory.memory());
- *ptr = 0;
-
- // Start |kNumTasks| processes, each of which atomically increments the first
- // word by 1.
- Process processes[kNumTasks];
- for (int index = 0; index < kNumTasks; ++index) {
- processes[index] = SpawnChild("SharedMemoryTestMain");
- ASSERT_TRUE(processes[index].IsValid());
- }
-
- // Check that each process exited correctly.
- int exit_code = 0;
- for (int index = 0; index < kNumTasks; ++index) {
- EXPECT_TRUE(processes[index].WaitForExit(&exit_code));
- EXPECT_EQ(0, exit_code);
- }
-
- // Check that the shared memory region reflects |kNumTasks| increments.
- ASSERT_EQ(kNumTasks, *ptr);
-
- memory.Close();
- SharedMemoryProcessTest::CleanUp();
-}
-
-MULTIPROCESS_TEST_MAIN(SharedMemoryTestMain) {
- return SharedMemoryProcessTest::TaskTestMain();
-}
-#endif // !defined(OS_IOS) && !defined(OS_ANDROID) && !defined(OS_MACOSX) &&
- // !defined(OS_FUCHSIA)
-
-TEST_P(SharedMemoryTest, MappedId) {
- const uint32_t kDataSize = 1024;
- SharedMemory memory;
- SharedMemoryCreateOptions options;
- options.size = kDataSize;
-#if defined(OS_MACOSX) && !defined(OS_IOS)
- // The Mach functionality is tested in shared_memory_mac_unittest.cc.
- options.type = SharedMemoryHandle::POSIX;
-#endif
-
- EXPECT_TRUE(memory.Create(options));
- base::UnguessableToken id = memory.handle().GetGUID();
- EXPECT_FALSE(id.is_empty());
- EXPECT_TRUE(memory.mapped_id().is_empty());
-
- EXPECT_TRUE(memory.Map(kDataSize));
- EXPECT_EQ(id, memory.mapped_id());
-
- memory.Close();
- EXPECT_EQ(id, memory.mapped_id());
-
- memory.Unmap();
- EXPECT_TRUE(memory.mapped_id().is_empty());
-}
-
-INSTANTIATE_TEST_CASE_P(Default,
- SharedMemoryTest,
- ::testing::Values(Mode::Default));
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
-INSTANTIATE_TEST_CASE_P(SkipDevShm,
- SharedMemoryTest,
- ::testing::Values(Mode::DisableDevShm));
-#endif // defined(OS_LINUX) && !defined(OS_CHROMEOS)
-
-#if defined(OS_ANDROID)
-TEST(SharedMemoryTest, ReadOnlyRegions) {
- const uint32_t kDataSize = 1024;
- SharedMemory memory;
- SharedMemoryCreateOptions options;
- options.size = kDataSize;
- EXPECT_TRUE(memory.Create(options));
-
- EXPECT_FALSE(memory.handle().IsRegionReadOnly());
-
- // Check that it is possible to map the region directly from the fd.
- int region_fd = memory.handle().GetHandle();
- EXPECT_GE(region_fd, 0);
- void* address = mmap(nullptr, kDataSize, PROT_READ | PROT_WRITE, MAP_SHARED,
- region_fd, 0);
- bool success = address && address != MAP_FAILED;
- ASSERT_TRUE(address);
- ASSERT_NE(address, MAP_FAILED);
- if (success) {
- EXPECT_EQ(0, munmap(address, kDataSize));
- }
-
- ASSERT_TRUE(memory.handle().SetRegionReadOnly());
- EXPECT_TRUE(memory.handle().IsRegionReadOnly());
-
- // Check that it is no longer possible to map the region read/write.
- errno = 0;
- address = mmap(nullptr, kDataSize, PROT_READ | PROT_WRITE, MAP_SHARED,
- region_fd, 0);
- success = address && address != MAP_FAILED;
- ASSERT_FALSE(success);
- ASSERT_EQ(EPERM, errno);
- if (success) {
- EXPECT_EQ(0, munmap(address, kDataSize));
- }
-}
-
-TEST(SharedMemoryTest, ReadOnlyDescriptors) {
- const uint32_t kDataSize = 1024;
- SharedMemory memory;
- SharedMemoryCreateOptions options;
- options.size = kDataSize;
- EXPECT_TRUE(memory.Create(options));
-
- EXPECT_FALSE(memory.handle().IsRegionReadOnly());
-
- // Getting a read-only descriptor should not make the region read-only itself.
- SharedMemoryHandle ro_handle = memory.GetReadOnlyHandle();
- EXPECT_FALSE(memory.handle().IsRegionReadOnly());
-
- // Mapping a writable region from a read-only descriptor should not
- // be possible, it will DCHECK() in debug builds (see test below),
- // while returning false on release ones.
- {
- bool dcheck_fired = false;
- logging::ScopedLogAssertHandler log_assert(
- base::BindRepeating([](bool* flag, const char*, int, base::StringPiece,
- base::StringPiece) { *flag = true; },
- base::Unretained(&dcheck_fired)));
-
- SharedMemory rw_region(ro_handle.Duplicate(), /* read_only */ false);
- EXPECT_FALSE(rw_region.Map(kDataSize));
- EXPECT_EQ(DCHECK_IS_ON() ? true : false, dcheck_fired);
- }
-
- // Nor shall it turn the region read-only itself.
- EXPECT_FALSE(ro_handle.IsRegionReadOnly());
-
- // Mapping a read-only region from a read-only descriptor should work.
- SharedMemory ro_region(ro_handle.Duplicate(), /* read_only */ true);
- EXPECT_TRUE(ro_region.Map(kDataSize));
-
- // And it should turn the region read-only too.
- EXPECT_TRUE(ro_handle.IsRegionReadOnly());
- EXPECT_TRUE(memory.handle().IsRegionReadOnly());
- EXPECT_FALSE(memory.Map(kDataSize));
-
- ro_handle.Close();
-}
-
-#endif // OS_ANDROID
-
-} // namespace base
diff --git a/base/memory/shared_memory_win_unittest.cc b/base/memory/shared_memory_win_unittest.cc
deleted file mode 100644
index 5fc132d..0000000
--- a/base/memory/shared_memory_win_unittest.cc
+++ /dev/null
@@ -1,224 +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 <windows.h>
-#include <sddl.h>
-
-#include <memory>
-
-#include "base/command_line.h"
-#include "base/memory/free_deleter.h"
-#include "base/memory/shared_memory.h"
-#include "base/process/process.h"
-#include "base/rand_util.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/win_util.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-namespace {
-const char* kHandleSwitchName = "shared_memory_win_test_switch";
-
-// Creates a process token with a low integrity SID.
-win::ScopedHandle CreateLowIntegritySID() {
- HANDLE process_token_raw = nullptr;
- BOOL success = ::OpenProcessToken(GetCurrentProcess(),
- TOKEN_DUPLICATE | TOKEN_ADJUST_DEFAULT |
- TOKEN_QUERY | TOKEN_ASSIGN_PRIMARY,
- &process_token_raw);
- if (!success)
- return base::win::ScopedHandle();
- win::ScopedHandle process_token(process_token_raw);
-
- HANDLE lowered_process_token_raw = nullptr;
- success =
- ::DuplicateTokenEx(process_token.Get(), 0, NULL, SecurityImpersonation,
- TokenPrimary, &lowered_process_token_raw);
- if (!success)
- return base::win::ScopedHandle();
- win::ScopedHandle lowered_process_token(lowered_process_token_raw);
-
- // Low integrity SID
- WCHAR integrity_sid_string[20] = L"S-1-16-4096";
- PSID integrity_sid = nullptr;
- success = ::ConvertStringSidToSid(integrity_sid_string, &integrity_sid);
- if (!success)
- return base::win::ScopedHandle();
-
- TOKEN_MANDATORY_LABEL TIL = {};
- TIL.Label.Attributes = SE_GROUP_INTEGRITY;
- TIL.Label.Sid = integrity_sid;
- success = ::SetTokenInformation(
- lowered_process_token.Get(), TokenIntegrityLevel, &TIL,
- sizeof(TOKEN_MANDATORY_LABEL) + GetLengthSid(integrity_sid));
- if (!success)
- return base::win::ScopedHandle();
- return lowered_process_token;
-}
-
-// Reads a HANDLE from the pipe as a raw int, least significant digit first.
-win::ScopedHandle ReadHandleFromPipe(HANDLE pipe) {
- // Read from parent pipe.
- const size_t buf_size = 1000;
- char buffer[buf_size];
- memset(buffer, 0, buf_size);
- DWORD bytes_read;
- BOOL success = ReadFile(pipe, buffer, buf_size, &bytes_read, NULL);
-
- if (!success || bytes_read == 0) {
- LOG(ERROR) << "Failed to read handle from pipe.";
- return win::ScopedHandle();
- }
-
- int handle_as_int = 0;
- int power_of_ten = 1;
- for (unsigned int i = 0; i < bytes_read; ++i) {
- handle_as_int += buffer[i] * power_of_ten;
- power_of_ten *= 10;
- }
-
- return win::ScopedHandle(reinterpret_cast<HANDLE>(handle_as_int));
-}
-
-// Writes a HANDLE to a pipe as a raw int, least significant digit first.
-void WriteHandleToPipe(HANDLE pipe, HANDLE handle) {
- uint32_t handle_as_int = base::win::HandleToUint32(handle);
-
- std::unique_ptr<char, base::FreeDeleter> buffer(
- static_cast<char*>(malloc(1000)));
- size_t index = 0;
- while (handle_as_int > 0) {
- buffer.get()[index] = handle_as_int % 10;
- handle_as_int /= 10;
- ++index;
- }
-
- ::ConnectNamedPipe(pipe, nullptr);
- DWORD written;
- ASSERT_TRUE(::WriteFile(pipe, buffer.get(), index, &written, NULL));
-}
-
-// Creates a communication pipe with the given name.
-win::ScopedHandle CreateCommunicationPipe(const std::wstring& name) {
- return win::ScopedHandle(CreateNamedPipe(name.c_str(), // pipe name
- PIPE_ACCESS_DUPLEX, PIPE_WAIT, 255,
- 1000, 1000, 0, NULL));
-}
-
-// Generates a random name for a communication pipe.
-std::wstring CreateCommunicationPipeName() {
- uint64_t rand_values[4];
- RandBytes(&rand_values, sizeof(rand_values));
- std::wstring child_pipe_name = StringPrintf(
- L"\\\\.\\pipe\\SharedMemoryWinTest_%016llx%016llx%016llx%016llx",
- rand_values[0], rand_values[1], rand_values[2], rand_values[3]);
- return child_pipe_name;
-}
-
-class SharedMemoryWinTest : public base::MultiProcessTest {
- protected:
- CommandLine MakeCmdLine(const std::string& procname) override {
- CommandLine line = base::MultiProcessTest::MakeCmdLine(procname);
- line.AppendSwitchASCII(kHandleSwitchName, communication_pipe_name_);
- return line;
- }
-
- std::string communication_pipe_name_;
-};
-
-MULTIPROCESS_TEST_MAIN(LowerPermissions) {
- std::string handle_name =
- CommandLine::ForCurrentProcess()->GetSwitchValueASCII(kHandleSwitchName);
- std::wstring handle_name16 = SysUTF8ToWide(handle_name);
- win::ScopedHandle parent_pipe(
- ::CreateFile(handle_name16.c_str(), // pipe name
- GENERIC_READ,
- 0, // no sharing
- NULL, // default security attributes
- OPEN_EXISTING, // opens existing pipe
- 0, // default attributes
- NULL)); // no template file
- if (parent_pipe.Get() == INVALID_HANDLE_VALUE) {
- LOG(ERROR) << "Failed to open communication pipe.";
- return 1;
- }
-
- win::ScopedHandle received_handle = ReadHandleFromPipe(parent_pipe.Get());
- if (!received_handle.Get()) {
- LOG(ERROR) << "Failed to read handle from pipe.";
- return 1;
- }
-
- // Attempting to add the WRITE_DAC permission should fail.
- HANDLE duped_handle;
- BOOL success = ::DuplicateHandle(GetCurrentProcess(), received_handle.Get(),
- GetCurrentProcess(), &duped_handle,
- FILE_MAP_READ | WRITE_DAC, FALSE, 0);
- if (success) {
- LOG(ERROR) << "Should not have been able to add WRITE_DAC permission.";
- return 1;
- }
-
- // Attempting to add the FILE_MAP_WRITE permission should fail.
- success = ::DuplicateHandle(GetCurrentProcess(), received_handle.Get(),
- GetCurrentProcess(), &duped_handle,
- FILE_MAP_READ | FILE_MAP_WRITE, FALSE, 0);
- if (success) {
- LOG(ERROR) << "Should not have been able to add FILE_MAP_WRITE permission.";
- return 1;
- }
-
- // Attempting to duplicate the HANDLE with the same permissions should
- // succeed.
- success = ::DuplicateHandle(GetCurrentProcess(), received_handle.Get(),
- GetCurrentProcess(), &duped_handle, FILE_MAP_READ,
- FALSE, 0);
- if (!success) {
- LOG(ERROR) << "Failed to duplicate handle.";
- return 4;
- }
- ::CloseHandle(duped_handle);
- return 0;
-}
-
-TEST_F(SharedMemoryWinTest, LowerPermissions) {
- std::wstring communication_pipe_name = CreateCommunicationPipeName();
- communication_pipe_name_ = SysWideToUTF8(communication_pipe_name);
-
- win::ScopedHandle communication_pipe =
- CreateCommunicationPipe(communication_pipe_name);
- ASSERT_TRUE(communication_pipe.Get());
-
- win::ScopedHandle lowered_process_token = CreateLowIntegritySID();
- ASSERT_TRUE(lowered_process_token.Get());
-
- base::LaunchOptions options;
- options.as_user = lowered_process_token.Get();
- base::Process process = SpawnChildWithOptions("LowerPermissions", options);
- ASSERT_TRUE(process.IsValid());
-
- SharedMemory memory;
- memory.CreateAndMapAnonymous(1001);
-
- // Duplicate into child process, giving only FILE_MAP_READ permissions.
- HANDLE raw_handle = nullptr;
- ::DuplicateHandle(::GetCurrentProcess(), memory.handle().GetHandle(),
- process.Handle(), &raw_handle,
- FILE_MAP_READ | SECTION_QUERY, FALSE, 0);
- ASSERT_TRUE(raw_handle);
-
- WriteHandleToPipe(communication_pipe.Get(), raw_handle);
-
- int exit_code;
- EXPECT_TRUE(process.WaitForExitWithTimeout(TestTimeouts::action_max_timeout(),
- &exit_code));
- EXPECT_EQ(0, exit_code);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/memory/singleton_unittest.cc b/base/memory/singleton_unittest.cc
deleted file mode 100644
index 06e53b2..0000000
--- a/base/memory/singleton_unittest.cc
+++ /dev/null
@@ -1,299 +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 <stdint.h>
-
-#include "base/at_exit.h"
-#include "base/memory/singleton.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-static_assert(DefaultSingletonTraits<int>::kRegisterAtExit == true,
- "object must be deleted on process exit");
-
-typedef void (*CallbackFunc)();
-
-template <size_t alignment>
-class AlignedData {
- public:
- AlignedData() = default;
- ~AlignedData() = default;
- alignas(alignment) char data_[alignment];
-};
-
-class IntSingleton {
- public:
- static IntSingleton* GetInstance() {
- return Singleton<IntSingleton>::get();
- }
-
- int value_;
-};
-
-class Init5Singleton {
- public:
- struct Trait;
-
- static Init5Singleton* GetInstance() {
- return Singleton<Init5Singleton, Trait>::get();
- }
-
- int value_;
-};
-
-struct Init5Singleton::Trait : public DefaultSingletonTraits<Init5Singleton> {
- static Init5Singleton* New() {
- Init5Singleton* instance = new Init5Singleton();
- instance->value_ = 5;
- return instance;
- }
-};
-
-int* SingletonInt() {
- return &IntSingleton::GetInstance()->value_;
-}
-
-int* SingletonInt5() {
- return &Init5Singleton::GetInstance()->value_;
-}
-
-template <typename Type>
-struct CallbackTrait : public DefaultSingletonTraits<Type> {
- static void Delete(Type* instance) {
- if (instance->callback_)
- (instance->callback_)();
- DefaultSingletonTraits<Type>::Delete(instance);
- }
-};
-
-class CallbackSingleton {
- public:
- CallbackSingleton() : callback_(nullptr) {}
- CallbackFunc callback_;
-};
-
-class CallbackSingletonWithNoLeakTrait : public CallbackSingleton {
- public:
- struct Trait : public CallbackTrait<CallbackSingletonWithNoLeakTrait> { };
-
- CallbackSingletonWithNoLeakTrait() : CallbackSingleton() { }
-
- static CallbackSingletonWithNoLeakTrait* GetInstance() {
- return Singleton<CallbackSingletonWithNoLeakTrait, Trait>::get();
- }
-};
-
-class CallbackSingletonWithLeakTrait : public CallbackSingleton {
- public:
- struct Trait : public CallbackTrait<CallbackSingletonWithLeakTrait> {
- static const bool kRegisterAtExit = false;
- };
-
- CallbackSingletonWithLeakTrait() : CallbackSingleton() { }
-
- static CallbackSingletonWithLeakTrait* GetInstance() {
- return Singleton<CallbackSingletonWithLeakTrait, Trait>::get();
- }
-};
-
-class CallbackSingletonWithStaticTrait : public CallbackSingleton {
- public:
- struct Trait;
-
- CallbackSingletonWithStaticTrait() : CallbackSingleton() { }
-
- static CallbackSingletonWithStaticTrait* GetInstance() {
- return Singleton<CallbackSingletonWithStaticTrait, Trait>::get();
- }
-};
-
-struct CallbackSingletonWithStaticTrait::Trait
- : public StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait> {
- static void Delete(CallbackSingletonWithStaticTrait* instance) {
- if (instance->callback_)
- (instance->callback_)();
- StaticMemorySingletonTraits<CallbackSingletonWithStaticTrait>::Delete(
- instance);
- }
-};
-
-template <class Type>
-class AlignedTestSingleton {
- public:
- AlignedTestSingleton() = default;
- ~AlignedTestSingleton() = default;
- static AlignedTestSingleton* GetInstance() {
- return Singleton<AlignedTestSingleton,
- StaticMemorySingletonTraits<AlignedTestSingleton>>::get();
- }
-
- Type type_;
-};
-
-
-void SingletonNoLeak(CallbackFunc CallOnQuit) {
- CallbackSingletonWithNoLeakTrait::GetInstance()->callback_ = CallOnQuit;
-}
-
-void SingletonLeak(CallbackFunc CallOnQuit) {
- CallbackSingletonWithLeakTrait::GetInstance()->callback_ = CallOnQuit;
-}
-
-CallbackFunc* GetLeakySingleton() {
- return &CallbackSingletonWithLeakTrait::GetInstance()->callback_;
-}
-
-void DeleteLeakySingleton() {
- DefaultSingletonTraits<CallbackSingletonWithLeakTrait>::Delete(
- CallbackSingletonWithLeakTrait::GetInstance());
-}
-
-void SingletonStatic(CallbackFunc CallOnQuit) {
- CallbackSingletonWithStaticTrait::GetInstance()->callback_ = CallOnQuit;
-}
-
-CallbackFunc* GetStaticSingleton() {
- return &CallbackSingletonWithStaticTrait::GetInstance()->callback_;
-}
-
-
-class SingletonTest : public testing::Test {
- public:
- SingletonTest() = default;
-
- void SetUp() override {
- non_leak_called_ = false;
- leaky_called_ = false;
- static_called_ = false;
- }
-
- protected:
- void VerifiesCallbacks() {
- EXPECT_TRUE(non_leak_called_);
- EXPECT_FALSE(leaky_called_);
- EXPECT_TRUE(static_called_);
- non_leak_called_ = false;
- leaky_called_ = false;
- static_called_ = false;
- }
-
- void VerifiesCallbacksNotCalled() {
- EXPECT_FALSE(non_leak_called_);
- EXPECT_FALSE(leaky_called_);
- EXPECT_FALSE(static_called_);
- non_leak_called_ = false;
- leaky_called_ = false;
- static_called_ = false;
- }
-
- static void CallbackNoLeak() {
- non_leak_called_ = true;
- }
-
- static void CallbackLeak() {
- leaky_called_ = true;
- }
-
- static void CallbackStatic() {
- static_called_ = true;
- }
-
- private:
- static bool non_leak_called_;
- static bool leaky_called_;
- static bool static_called_;
-};
-
-bool SingletonTest::non_leak_called_ = false;
-bool SingletonTest::leaky_called_ = false;
-bool SingletonTest::static_called_ = false;
-
-TEST_F(SingletonTest, Basic) {
- int* singleton_int;
- int* singleton_int_5;
- CallbackFunc* leaky_singleton;
- CallbackFunc* static_singleton;
-
- {
- ShadowingAtExitManager sem;
- {
- singleton_int = SingletonInt();
- }
- // Ensure POD type initialization.
- EXPECT_EQ(*singleton_int, 0);
- *singleton_int = 1;
-
- EXPECT_EQ(singleton_int, SingletonInt());
- EXPECT_EQ(*singleton_int, 1);
-
- {
- singleton_int_5 = SingletonInt5();
- }
- // Is default initialized to 5.
- EXPECT_EQ(*singleton_int_5, 5);
-
- SingletonNoLeak(&CallbackNoLeak);
- SingletonLeak(&CallbackLeak);
- SingletonStatic(&CallbackStatic);
- static_singleton = GetStaticSingleton();
- leaky_singleton = GetLeakySingleton();
- EXPECT_TRUE(leaky_singleton);
- }
-
- // Verify that only the expected callback has been called.
- VerifiesCallbacks();
- // Delete the leaky singleton.
- DeleteLeakySingleton();
-
- // The static singleton can't be acquired post-atexit.
- EXPECT_EQ(nullptr, GetStaticSingleton());
-
- {
- ShadowingAtExitManager sem;
- // Verifiy that the variables were reset.
- {
- singleton_int = SingletonInt();
- EXPECT_EQ(*singleton_int, 0);
- }
- {
- singleton_int_5 = SingletonInt5();
- EXPECT_EQ(*singleton_int_5, 5);
- }
- {
- // Resurrect the static singleton, and assert that it
- // still points to the same (static) memory.
- CallbackSingletonWithStaticTrait::Trait::ResurrectForTesting();
- EXPECT_EQ(GetStaticSingleton(), static_singleton);
- }
- }
- // The leaky singleton shouldn't leak since SingletonLeak has not been called.
- VerifiesCallbacksNotCalled();
-}
-
-#define EXPECT_ALIGNED(ptr, align) \
- EXPECT_EQ(0u, reinterpret_cast<uintptr_t>(ptr) & (align - 1))
-
-TEST_F(SingletonTest, Alignment) {
- // Create some static singletons with increasing sizes and alignment
- // requirements. By ordering this way, the linker will need to do some work to
- // ensure proper alignment of the static data.
- AlignedTestSingleton<int32_t>* align4 =
- AlignedTestSingleton<int32_t>::GetInstance();
- AlignedTestSingleton<AlignedData<32>>* align32 =
- AlignedTestSingleton<AlignedData<32>>::GetInstance();
- AlignedTestSingleton<AlignedData<128>>* align128 =
- AlignedTestSingleton<AlignedData<128>>::GetInstance();
- AlignedTestSingleton<AlignedData<4096>>* align4096 =
- AlignedTestSingleton<AlignedData<4096>>::GetInstance();
-
- EXPECT_ALIGNED(align4, 4);
- EXPECT_ALIGNED(align32, 32);
- EXPECT_ALIGNED(align128, 128);
- EXPECT_ALIGNED(align4096, 4096);
-}
-
-} // namespace
-} // namespace base
diff --git a/base/memory/weak_ptr_unittest.cc b/base/memory/weak_ptr_unittest.cc
deleted file mode 100644
index f8dfb7c..0000000
--- a/base/memory/weak_ptr_unittest.cc
+++ /dev/null
@@ -1,716 +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/memory/weak_ptr.h"
-
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/debug/leak_annotations.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-WeakPtr<int> PassThru(WeakPtr<int> ptr) {
- return ptr;
-}
-
-template <class T>
-class OffThreadObjectCreator {
- public:
- static T* NewObject() {
- T* result;
- {
- Thread creator_thread("creator_thread");
- creator_thread.Start();
- creator_thread.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(OffThreadObjectCreator::CreateObject, &result));
- }
- DCHECK(result); // We synchronized on thread destruction above.
- return result;
- }
- private:
- static void CreateObject(T** result) {
- *result = new T;
- }
-};
-
-struct Base {
- std::string member;
-};
-struct Derived : public Base {};
-
-struct TargetBase {};
-struct Target : public TargetBase, public SupportsWeakPtr<Target> {
- virtual ~Target() = default;
-};
-
-struct DerivedTarget : public Target {};
-
-// A class inheriting from Target and defining a nested type called 'Base'.
-// To guard against strange compilation errors.
-struct DerivedTargetWithNestedBase : public Target {
- using Base = void;
-};
-
-// A struct with a virtual destructor.
-struct VirtualDestructor {
- virtual ~VirtualDestructor() = default;
-};
-
-// A class inheriting from Target where Target is not the first base, and where
-// the first base has a virtual method table. This creates a structure where the
-// Target base is not positioned at the beginning of
-// DerivedTargetMultipleInheritance.
-struct DerivedTargetMultipleInheritance : public VirtualDestructor,
- public Target {};
-
-struct Arrow {
- WeakPtr<Target> target;
-};
-struct TargetWithFactory : public Target {
- TargetWithFactory() : factory(this) {}
- WeakPtrFactory<Target> factory;
-};
-
-// Helper class to create and destroy weak pointer copies
-// and delete objects on a background thread.
-class BackgroundThread : public Thread {
- public:
- BackgroundThread() : Thread("owner_thread") {}
-
- ~BackgroundThread() override { Stop(); }
-
- void CreateArrowFromTarget(Arrow** arrow, Target* target) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromTarget,
- arrow, target, &completion));
- completion.Wait();
- }
-
- void CreateArrowFromArrow(Arrow** arrow, const Arrow* other) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&BackgroundThread::DoCreateArrowFromArrow,
- arrow, other, &completion));
- completion.Wait();
- }
-
- void DeleteTarget(Target* object) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&BackgroundThread::DoDeleteTarget, object, &completion));
- completion.Wait();
- }
-
- void CopyAndAssignArrow(Arrow* object) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrow,
- object, &completion));
- completion.Wait();
- }
-
- void CopyAndAssignArrowBase(Arrow* object) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&BackgroundThread::DoCopyAndAssignArrowBase,
- object, &completion));
- completion.Wait();
- }
-
- void DeleteArrow(Arrow* object) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&BackgroundThread::DoDeleteArrow, object, &completion));
- completion.Wait();
- }
-
- Target* DeRef(const Arrow* arrow) {
- WaitableEvent completion(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- Target* result = nullptr;
- task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&BackgroundThread::DoDeRef, arrow, &result,
- &completion));
- completion.Wait();
- return result;
- }
-
- protected:
- static void DoCreateArrowFromArrow(Arrow** arrow,
- const Arrow* other,
- WaitableEvent* completion) {
- *arrow = new Arrow;
- **arrow = *other;
- completion->Signal();
- }
-
- static void DoCreateArrowFromTarget(Arrow** arrow,
- Target* target,
- WaitableEvent* completion) {
- *arrow = new Arrow;
- (*arrow)->target = target->AsWeakPtr();
- completion->Signal();
- }
-
- static void DoDeRef(const Arrow* arrow,
- Target** result,
- WaitableEvent* completion) {
- *result = arrow->target.get();
- completion->Signal();
- }
-
- static void DoDeleteTarget(Target* object, WaitableEvent* completion) {
- delete object;
- completion->Signal();
- }
-
- static void DoCopyAndAssignArrow(Arrow* object, WaitableEvent* completion) {
- // Copy constructor.
- Arrow a = *object;
- // Assignment operator.
- *object = a;
- completion->Signal();
- }
-
- static void DoCopyAndAssignArrowBase(
- Arrow* object,
- WaitableEvent* completion) {
- // Copy constructor.
- WeakPtr<TargetBase> b = object->target;
- // Assignment operator.
- WeakPtr<TargetBase> c;
- c = object->target;
- completion->Signal();
- }
-
- static void DoDeleteArrow(Arrow* object, WaitableEvent* completion) {
- delete object;
- completion->Signal();
- }
-};
-
-} // namespace
-
-TEST(WeakPtrFactoryTest, Basic) {
- int data;
- WeakPtrFactory<int> factory(&data);
- WeakPtr<int> ptr = factory.GetWeakPtr();
- EXPECT_EQ(&data, ptr.get());
-}
-
-TEST(WeakPtrFactoryTest, Comparison) {
- int data;
- WeakPtrFactory<int> factory(&data);
- WeakPtr<int> ptr = factory.GetWeakPtr();
- WeakPtr<int> ptr2 = ptr;
- EXPECT_EQ(ptr.get(), ptr2.get());
-}
-
-TEST(WeakPtrFactoryTest, Move) {
- int data;
- WeakPtrFactory<int> factory(&data);
- WeakPtr<int> ptr = factory.GetWeakPtr();
- WeakPtr<int> ptr2 = factory.GetWeakPtr();
- WeakPtr<int> ptr3 = std::move(ptr2);
- EXPECT_NE(ptr.get(), ptr2.get());
- EXPECT_EQ(ptr.get(), ptr3.get());
-}
-
-TEST(WeakPtrFactoryTest, OutOfScope) {
- WeakPtr<int> ptr;
- EXPECT_EQ(nullptr, ptr.get());
- {
- int data;
- WeakPtrFactory<int> factory(&data);
- ptr = factory.GetWeakPtr();
- }
- EXPECT_EQ(nullptr, ptr.get());
-}
-
-TEST(WeakPtrFactoryTest, Multiple) {
- WeakPtr<int> a, b;
- {
- int data;
- WeakPtrFactory<int> factory(&data);
- a = factory.GetWeakPtr();
- b = factory.GetWeakPtr();
- EXPECT_EQ(&data, a.get());
- EXPECT_EQ(&data, b.get());
- }
- EXPECT_EQ(nullptr, a.get());
- EXPECT_EQ(nullptr, b.get());
-}
-
-TEST(WeakPtrFactoryTest, MultipleStaged) {
- WeakPtr<int> a;
- {
- int data;
- WeakPtrFactory<int> factory(&data);
- a = factory.GetWeakPtr();
- {
- WeakPtr<int> b = factory.GetWeakPtr();
- }
- EXPECT_NE(nullptr, a.get());
- }
- EXPECT_EQ(nullptr, a.get());
-}
-
-TEST(WeakPtrFactoryTest, Dereference) {
- Base data;
- data.member = "123456";
- WeakPtrFactory<Base> factory(&data);
- WeakPtr<Base> ptr = factory.GetWeakPtr();
- EXPECT_EQ(&data, ptr.get());
- EXPECT_EQ(data.member, (*ptr).member);
- EXPECT_EQ(data.member, ptr->member);
-}
-
-TEST(WeakPtrFactoryTest, UpCast) {
- Derived data;
- WeakPtrFactory<Derived> factory(&data);
- WeakPtr<Base> ptr = factory.GetWeakPtr();
- ptr = factory.GetWeakPtr();
- EXPECT_EQ(ptr.get(), &data);
-}
-
-TEST(WeakPtrTest, ConstructFromNullptr) {
- WeakPtr<int> ptr = PassThru(nullptr);
- EXPECT_EQ(nullptr, ptr.get());
-}
-
-TEST(WeakPtrTest, SupportsWeakPtr) {
- Target target;
- WeakPtr<Target> ptr = target.AsWeakPtr();
- EXPECT_EQ(&target, ptr.get());
-}
-
-TEST(WeakPtrTest, DerivedTarget) {
- DerivedTarget target;
- WeakPtr<DerivedTarget> ptr = AsWeakPtr(&target);
- EXPECT_EQ(&target, ptr.get());
-}
-
-TEST(WeakPtrTest, DerivedTargetWithNestedBase) {
- DerivedTargetWithNestedBase target;
- WeakPtr<DerivedTargetWithNestedBase> ptr = AsWeakPtr(&target);
- EXPECT_EQ(&target, ptr.get());
-}
-
-TEST(WeakPtrTest, DerivedTargetMultipleInheritance) {
- DerivedTargetMultipleInheritance d;
- Target& b = d;
- EXPECT_NE(static_cast<void*>(&d), static_cast<void*>(&b));
- const WeakPtr<Target> pb = AsWeakPtr(&b);
- EXPECT_EQ(pb.get(), &b);
- const WeakPtr<DerivedTargetMultipleInheritance> pd = AsWeakPtr(&d);
- EXPECT_EQ(pd.get(), &d);
-}
-
-TEST(WeakPtrFactoryTest, BooleanTesting) {
- int data;
- WeakPtrFactory<int> factory(&data);
-
- WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
- EXPECT_TRUE(ptr_to_an_instance);
- EXPECT_FALSE(!ptr_to_an_instance);
-
- if (ptr_to_an_instance) {
- } else {
- ADD_FAILURE() << "Pointer to an instance should result in true.";
- }
-
- if (!ptr_to_an_instance) { // check for operator!().
- ADD_FAILURE() << "Pointer to an instance should result in !x being false.";
- }
-
- WeakPtr<int> null_ptr;
- EXPECT_FALSE(null_ptr);
- EXPECT_TRUE(!null_ptr);
-
- if (null_ptr) {
- ADD_FAILURE() << "Null pointer should result in false.";
- }
-
- if (!null_ptr) { // check for operator!().
- } else {
- ADD_FAILURE() << "Null pointer should result in !x being true.";
- }
-}
-
-TEST(WeakPtrFactoryTest, ComparisonToNull) {
- int data;
- WeakPtrFactory<int> factory(&data);
-
- WeakPtr<int> ptr_to_an_instance = factory.GetWeakPtr();
- EXPECT_NE(nullptr, ptr_to_an_instance);
- EXPECT_NE(ptr_to_an_instance, nullptr);
-
- WeakPtr<int> null_ptr;
- EXPECT_EQ(null_ptr, nullptr);
- EXPECT_EQ(nullptr, null_ptr);
-}
-
-TEST(WeakPtrTest, InvalidateWeakPtrs) {
- int data;
- WeakPtrFactory<int> factory(&data);
- WeakPtr<int> ptr = factory.GetWeakPtr();
- EXPECT_EQ(&data, ptr.get());
- EXPECT_TRUE(factory.HasWeakPtrs());
- factory.InvalidateWeakPtrs();
- EXPECT_EQ(nullptr, ptr.get());
- EXPECT_FALSE(factory.HasWeakPtrs());
-
- // Test that the factory can create new weak pointers after a
- // InvalidateWeakPtrs call, and they remain valid until the next
- // InvalidateWeakPtrs call.
- WeakPtr<int> ptr2 = factory.GetWeakPtr();
- EXPECT_EQ(&data, ptr2.get());
- EXPECT_TRUE(factory.HasWeakPtrs());
- factory.InvalidateWeakPtrs();
- EXPECT_EQ(nullptr, ptr2.get());
- EXPECT_FALSE(factory.HasWeakPtrs());
-}
-
-TEST(WeakPtrTest, HasWeakPtrs) {
- int data;
- WeakPtrFactory<int> factory(&data);
- {
- WeakPtr<int> ptr = factory.GetWeakPtr();
- EXPECT_TRUE(factory.HasWeakPtrs());
- }
- EXPECT_FALSE(factory.HasWeakPtrs());
-}
-
-TEST(WeakPtrTest, ObjectAndWeakPtrOnDifferentThreads) {
- // Test that it is OK to create an object that supports WeakPtr on one thread,
- // but use it on another. This tests that we do not trip runtime checks that
- // ensure that a WeakPtr is not used by multiple threads.
- std::unique_ptr<Target> target(OffThreadObjectCreator<Target>::NewObject());
- WeakPtr<Target> weak_ptr = target->AsWeakPtr();
- EXPECT_EQ(target.get(), weak_ptr.get());
-}
-
-TEST(WeakPtrTest, WeakPtrInitiateAndUseOnDifferentThreads) {
- // Test that it is OK to create an object that has a WeakPtr member on one
- // thread, but use it on another. This tests that we do not trip runtime
- // checks that ensure that a WeakPtr is not used by multiple threads.
- std::unique_ptr<Arrow> arrow(OffThreadObjectCreator<Arrow>::NewObject());
- Target target;
- arrow->target = target.AsWeakPtr();
- EXPECT_EQ(&target, arrow->target.get());
-}
-
-TEST(WeakPtrTest, MoveOwnershipImplicitly) {
- // Move object ownership to another thread by releasing all weak pointers
- // on the original thread first, and then establish WeakPtr on a different
- // thread.
- BackgroundThread background;
- background.Start();
-
- Target* target = new Target();
- {
- WeakPtr<Target> weak_ptr = target->AsWeakPtr();
- // Main thread deletes the WeakPtr, then the thread ownership of the
- // object can be implicitly moved.
- }
- Arrow* arrow;
-
- // Background thread creates WeakPtr(and implicitly owns the object).
- background.CreateArrowFromTarget(&arrow, target);
- EXPECT_EQ(background.DeRef(arrow), target);
-
- {
- // Main thread creates another WeakPtr, but this does not trigger implicitly
- // thread ownership move.
- Arrow arrow;
- arrow.target = target->AsWeakPtr();
-
- // The new WeakPtr is owned by background thread.
- EXPECT_EQ(target, background.DeRef(&arrow));
- }
-
- // Target can only be deleted on background thread.
- background.DeleteTarget(target);
- background.DeleteArrow(arrow);
-}
-
-TEST(WeakPtrTest, MoveOwnershipOfUnreferencedObject) {
- BackgroundThread background;
- background.Start();
-
- Arrow* arrow;
- {
- Target target;
- // Background thread creates WeakPtr.
- background.CreateArrowFromTarget(&arrow, &target);
-
- // Bind to background thread.
- EXPECT_EQ(&target, background.DeRef(arrow));
-
- // Release the only WeakPtr.
- arrow->target.reset();
-
- // Now we should be able to create a new reference from this thread.
- arrow->target = target.AsWeakPtr();
-
- // Re-bind to main thread.
- EXPECT_EQ(&target, arrow->target.get());
-
- // And the main thread can now delete the target.
- }
-
- delete arrow;
-}
-
-TEST(WeakPtrTest, MoveOwnershipAfterInvalidate) {
- BackgroundThread background;
- background.Start();
-
- Arrow arrow;
- std::unique_ptr<TargetWithFactory> target(new TargetWithFactory);
-
- // Bind to main thread.
- arrow.target = target->factory.GetWeakPtr();
- EXPECT_EQ(target.get(), arrow.target.get());
-
- target->factory.InvalidateWeakPtrs();
- EXPECT_EQ(nullptr, arrow.target.get());
-
- arrow.target = target->factory.GetWeakPtr();
- // Re-bind to background thread.
- EXPECT_EQ(target.get(), background.DeRef(&arrow));
-
- // And the background thread can now delete the target.
- background.DeleteTarget(target.release());
-}
-
-TEST(WeakPtrTest, MainThreadRefOutlivesBackgroundThreadRef) {
- // Originating thread has a WeakPtr that outlives others.
- // - Main thread creates a WeakPtr
- // - Background thread creates a WeakPtr copy from the one in main thread
- // - Destruct the WeakPtr on background thread
- // - Destruct the WeakPtr on main thread
- BackgroundThread background;
- background.Start();
-
- Target target;
- Arrow arrow;
- arrow.target = target.AsWeakPtr();
-
- Arrow* arrow_copy;
- background.CreateArrowFromArrow(&arrow_copy, &arrow);
- EXPECT_EQ(arrow_copy->target.get(), &target);
- background.DeleteArrow(arrow_copy);
-}
-
-TEST(WeakPtrTest, BackgroundThreadRefOutlivesMainThreadRef) {
- // Originating thread drops all references before another thread.
- // - Main thread creates a WeakPtr and passes copy to background thread
- // - Destruct the pointer on main thread
- // - Destruct the pointer on background thread
- BackgroundThread background;
- background.Start();
-
- Target target;
- Arrow* arrow_copy;
- {
- Arrow arrow;
- arrow.target = target.AsWeakPtr();
- background.CreateArrowFromArrow(&arrow_copy, &arrow);
- }
- EXPECT_EQ(arrow_copy->target.get(), &target);
- background.DeleteArrow(arrow_copy);
-}
-
-TEST(WeakPtrTest, OwnerThreadDeletesObject) {
- // Originating thread invalidates WeakPtrs while its held by other thread.
- // - Main thread creates WeakPtr and passes Copy to background thread
- // - Object gets destroyed on main thread
- // (invalidates WeakPtr on background thread)
- // - WeakPtr gets destroyed on Thread B
- BackgroundThread background;
- background.Start();
- Arrow* arrow_copy;
- {
- Target target;
- Arrow arrow;
- arrow.target = target.AsWeakPtr();
- background.CreateArrowFromArrow(&arrow_copy, &arrow);
- }
- EXPECT_EQ(nullptr, arrow_copy->target.get());
- background.DeleteArrow(arrow_copy);
-}
-
-TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtr) {
- // Main thread creates a Target object.
- Target target;
- // Main thread creates an arrow referencing the Target.
- Arrow *arrow = new Arrow();
- arrow->target = target.AsWeakPtr();
-
- // Background can copy and assign arrow (as well as the WeakPtr inside).
- BackgroundThread background;
- background.Start();
- background.CopyAndAssignArrow(arrow);
- background.DeleteArrow(arrow);
-}
-
-TEST(WeakPtrTest, NonOwnerThreadCanCopyAndAssignWeakPtrBase) {
- // Main thread creates a Target object.
- Target target;
- // Main thread creates an arrow referencing the Target.
- Arrow *arrow = new Arrow();
- arrow->target = target.AsWeakPtr();
-
- // Background can copy and assign arrow's WeakPtr to a base class WeakPtr.
- BackgroundThread background;
- background.Start();
- background.CopyAndAssignArrowBase(arrow);
- background.DeleteArrow(arrow);
-}
-
-TEST(WeakPtrTest, NonOwnerThreadCanDeleteWeakPtr) {
- // Main thread creates a Target object.
- Target target;
- // Main thread creates an arrow referencing the Target.
- Arrow* arrow = new Arrow();
- arrow->target = target.AsWeakPtr();
-
- // Background can delete arrow (as well as the WeakPtr inside).
- BackgroundThread background;
- background.Start();
- background.DeleteArrow(arrow);
-}
-
-TEST(WeakPtrDeathTest, WeakPtrCopyDoesNotChangeThreadBinding) {
- // The default style "fast" does not support multi-threaded tests
- // (introduces deadlock on Linux).
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-
- BackgroundThread background;
- background.Start();
-
- // Main thread creates a Target object.
- Target target;
- // Main thread creates an arrow referencing the Target.
- Arrow arrow;
- arrow.target = target.AsWeakPtr();
-
- // Background copies the WeakPtr.
- Arrow* arrow_copy;
- background.CreateArrowFromArrow(&arrow_copy, &arrow);
-
- // The copy is still bound to main thread so I can deref.
- EXPECT_EQ(arrow.target.get(), arrow_copy->target.get());
-
- // Although background thread created the copy, it can not deref the copied
- // WeakPtr.
- ASSERT_DCHECK_DEATH(background.DeRef(arrow_copy));
-
- background.DeleteArrow(arrow_copy);
-}
-
-TEST(WeakPtrDeathTest, NonOwnerThreadDereferencesWeakPtrAfterReference) {
- // The default style "fast" does not support multi-threaded tests
- // (introduces deadlock on Linux).
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-
- // Main thread creates a Target object.
- Target target;
-
- // Main thread creates an arrow referencing the Target (so target's
- // thread ownership can not be implicitly moved).
- Arrow arrow;
- arrow.target = target.AsWeakPtr();
- arrow.target.get();
-
- // Background thread tries to deref target, which violates thread ownership.
- BackgroundThread background;
- background.Start();
- ASSERT_DCHECK_DEATH(background.DeRef(&arrow));
-}
-
-TEST(WeakPtrDeathTest, NonOwnerThreadDeletesWeakPtrAfterReference) {
- // The default style "fast" does not support multi-threaded tests
- // (introduces deadlock on Linux).
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-
- std::unique_ptr<Target> target(new Target());
-
- // Main thread creates an arrow referencing the Target.
- Arrow arrow;
- arrow.target = target->AsWeakPtr();
-
- // Background thread tries to deref target, binding it to the thread.
- BackgroundThread background;
- background.Start();
- background.DeRef(&arrow);
-
- // Main thread deletes Target, violating thread binding.
- ASSERT_DCHECK_DEATH(target.reset());
-
- // |target.reset()| died so |target| still holds the object, so we
- // must pass it to the background thread to teardown.
- background.DeleteTarget(target.release());
-}
-
-TEST(WeakPtrDeathTest, NonOwnerThreadDeletesObjectAfterReference) {
- // The default style "fast" does not support multi-threaded tests
- // (introduces deadlock on Linux).
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-
- std::unique_ptr<Target> target(new Target());
-
- // Main thread creates an arrow referencing the Target, and references it, so
- // that it becomes bound to the thread.
- Arrow arrow;
- arrow.target = target->AsWeakPtr();
- arrow.target.get();
-
- // Background thread tries to delete target, volating thread binding.
- BackgroundThread background;
- background.Start();
- ASSERT_DCHECK_DEATH(background.DeleteTarget(target.release()));
-}
-
-TEST(WeakPtrDeathTest, NonOwnerThreadReferencesObjectAfterDeletion) {
- // The default style "fast" does not support multi-threaded tests
- // (introduces deadlock on Linux).
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
-
- std::unique_ptr<Target> target(new Target());
-
- // Main thread creates an arrow referencing the Target.
- Arrow arrow;
- arrow.target = target->AsWeakPtr();
-
- // Background thread tries to delete target, binding the object to the thread.
- BackgroundThread background;
- background.Start();
- background.DeleteTarget(target.release());
-
- // Main thread attempts to dereference the target, violating thread binding.
- ASSERT_DCHECK_DEATH(arrow.target.get());
-}
-
-} // namespace base
diff --git a/base/memory/weak_ptr_unittest.nc b/base/memory/weak_ptr_unittest.nc
deleted file mode 100644
index b96b033..0000000
--- a/base/memory/weak_ptr_unittest.nc
+++ /dev/null
@@ -1,144 +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 is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/memory/weak_ptr.h"
-
-namespace base {
-
-struct Producer : SupportsWeakPtr<Producer> {};
-struct DerivedProducer : Producer {};
-struct OtherDerivedProducer : Producer {};
-struct MultiplyDerivedProducer : Producer,
- SupportsWeakPtr<MultiplyDerivedProducer> {};
-struct Unrelated {};
-struct DerivedUnrelated : Unrelated {};
-
-#if defined(NCTEST_AUTO_DOWNCAST) // [r"cannot initialize a variable of type 'base::DerivedProducer \*' with an rvalue of type 'base::Producer \*'"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<Producer> ptr = f.AsWeakPtr();
- WeakPtr<DerivedProducer> derived_ptr = ptr;
-}
-
-#elif defined(NCTEST_STATIC_DOWNCAST) // [r"cannot initialize a variable of type 'base::DerivedProducer \*' with an rvalue of type 'base::Producer \*'"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<Producer> ptr = f.AsWeakPtr();
- WeakPtr<DerivedProducer> derived_ptr =
- static_cast<WeakPtr<DerivedProducer> >(ptr);
-}
-
-#elif defined(NCTEST_AUTO_REF_DOWNCAST) // [r"fatal error: non-const lvalue reference to type 'WeakPtr<base::DerivedProducer>' cannot bind to a value of unrelated type 'WeakPtr<base::Producer>'"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<Producer> ptr = f.AsWeakPtr();
- WeakPtr<DerivedProducer>& derived_ptr = ptr;
-}
-
-#elif defined(NCTEST_STATIC_REF_DOWNCAST) // [r"fatal error: non-const lvalue reference to type 'WeakPtr<base::DerivedProducer>' cannot bind to a value of unrelated type 'WeakPtr<base::Producer>'"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<Producer> ptr = f.AsWeakPtr();
- WeakPtr<DerivedProducer>& derived_ptr =
- static_cast<WeakPtr<DerivedProducer>&>(ptr);
-}
-
-#elif defined(NCTEST_STATIC_ASWEAKPTR_DOWNCAST) // [r"no matching function"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<DerivedProducer> ptr =
- SupportsWeakPtr<Producer>::StaticAsWeakPtr<DerivedProducer>(&f);
-}
-
-#elif defined(NCTEST_UNSAFE_HELPER_DOWNCAST) // [r"cannot initialize a variable of type 'base::DerivedProducer \*' with an rvalue of type 'base::Producer \*'"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<DerivedProducer> ptr = AsWeakPtr(&f);
-}
-
-#elif defined(NCTEST_UNSAFE_INSTANTIATED_HELPER_DOWNCAST) // [r"no matching function"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<DerivedProducer> ptr = AsWeakPtr<DerivedProducer>(&f);
-}
-
-#elif defined(NCTEST_UNSAFE_WRONG_INSANTIATED_HELPER_DOWNCAST) // [r"cannot initialize a variable of type 'base::DerivedProducer \*' with an rvalue of type 'base::Producer \*'"]
-
-void WontCompile() {
- Producer f;
- WeakPtr<DerivedProducer> ptr = AsWeakPtr<Producer>(&f);
-}
-
-#elif defined(NCTEST_UNSAFE_HELPER_CAST) // [r"cannot initialize a variable of type 'base::OtherDerivedProducer \*' with an rvalue of type 'base::DerivedProducer \*'"]
-
-void WontCompile() {
- DerivedProducer f;
- WeakPtr<OtherDerivedProducer> ptr = AsWeakPtr(&f);
-}
-
-#elif defined(NCTEST_UNSAFE_INSTANTIATED_HELPER_SIDECAST) // [r"fatal error: no matching function for call to 'AsWeakPtr'"]
-
-void WontCompile() {
- DerivedProducer f;
- WeakPtr<OtherDerivedProducer> ptr = AsWeakPtr<OtherDerivedProducer>(&f);
-}
-
-#elif defined(NCTEST_UNSAFE_WRONG_INSTANTIATED_HELPER_SIDECAST) // [r"cannot initialize a variable of type 'base::OtherDerivedProducer \*' with an rvalue of type 'base::DerivedProducer \*'"]
-
-void WontCompile() {
- DerivedProducer f;
- WeakPtr<OtherDerivedProducer> ptr = AsWeakPtr<DerivedProducer>(&f);
-}
-
-#elif defined(NCTEST_UNRELATED_HELPER) // [r"cannot initialize a variable of type 'base::Unrelated \*' with an rvalue of type 'base::DerivedProducer \*'"]
-
-void WontCompile() {
- DerivedProducer f;
- WeakPtr<Unrelated> ptr = AsWeakPtr(&f);
-}
-
-#elif defined(NCTEST_UNRELATED_INSTANTIATED_HELPER) // [r"no matching function"]
-
-void WontCompile() {
- DerivedProducer f;
- WeakPtr<Unrelated> ptr = AsWeakPtr<Unrelated>(&f);
-}
-
-// TODO(hans): Remove .* and update the static_assert expectations once we roll
-// past Clang r313315. https://crbug.com/765692.
-
-#elif defined(NCTEST_COMPLETELY_UNRELATED_HELPER) // [r"fatal error: static_assert failed .*\"AsWeakPtr argument must inherit from SupportsWeakPtr\""]
-
-void WontCompile() {
- Unrelated f;
- WeakPtr<Unrelated> ptr = AsWeakPtr(&f);
-}
-
-#elif defined(NCTEST_DERIVED_COMPLETELY_UNRELATED_HELPER) // [r"fatal error: static_assert failed .*\"AsWeakPtr argument must inherit from SupportsWeakPtr\""]
-
-void WontCompile() {
- DerivedUnrelated f;
- WeakPtr<Unrelated> ptr = AsWeakPtr(&f);
-}
-
-#elif defined(NCTEST_AMBIGUOUS_ANCESTORS) // [r"fatal error: use of undeclared identifier 'AsWeakPtrImpl'"]
-
-void WontCompile() {
- MultiplyDerivedProducer f;
- WeakPtr<MultiplyDerivedProducer> ptr = AsWeakPtr(&f);
-}
-
-#endif
-
-}
diff --git a/base/message_loop/message_loop_io_posix_unittest.cc b/base/message_loop/message_loop_io_posix_unittest.cc
deleted file mode 100644
index 9ecd606..0000000
--- a/base/message_loop/message_loop_io_posix_unittest.cc
+++ /dev/null
@@ -1,418 +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/message_loop/message_loop.h"
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/message_loop/message_pump_for_io.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/run_loop.h"
-#include "base/test/gtest_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-#if !defined(OS_NACL)
-
-namespace {
-
-class MessageLoopForIoPosixTest : public testing::Test {
- public:
- MessageLoopForIoPosixTest() = default;
-
- // testing::Test interface.
- void SetUp() override {
- // Create a file descriptor. Doesn't need to be readable or writable,
- // as we don't need to actually get any notifications.
- // pipe() is just the easiest way to do it.
- int pipefds[2];
- int err = pipe(pipefds);
- ASSERT_EQ(0, err);
- read_fd_ = ScopedFD(pipefds[0]);
- write_fd_ = ScopedFD(pipefds[1]);
- }
-
- void TriggerReadEvent() {
- // Write from the other end of the pipe to trigger the event.
- char c = '\0';
- EXPECT_EQ(1, HANDLE_EINTR(write(write_fd_.get(), &c, 1)));
- }
-
- protected:
- ScopedFD read_fd_;
- ScopedFD write_fd_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageLoopForIoPosixTest);
-};
-
-class TestHandler : public MessagePumpForIO::FdWatcher {
- public:
- void OnFileCanReadWithoutBlocking(int fd) override {
- watcher_to_delete_ = nullptr;
- is_readable_ = true;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
- void OnFileCanWriteWithoutBlocking(int fd) override {
- watcher_to_delete_ = nullptr;
- is_writable_ = true;
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- bool is_readable_ = false;
- bool is_writable_ = false;
-
- // If set then the contained watcher will be deleted on notification.
- std::unique_ptr<MessagePumpForIO::FdWatchController> watcher_to_delete_;
-};
-
-// Watcher that calls specified closures when read/write events occur. Verifies
-// that each non-null closure passed to this class is called once and only once.
-// Also resets the read event by reading from the FD.
-class CallClosureHandler : public MessagePumpForIO::FdWatcher {
- public:
- CallClosureHandler(OnceClosure read_closure, OnceClosure write_closure)
- : read_closure_(std::move(read_closure)),
- write_closure_(std::move(write_closure)) {}
-
- ~CallClosureHandler() override {
- EXPECT_TRUE(read_closure_.is_null());
- EXPECT_TRUE(write_closure_.is_null());
- }
-
- void SetReadClosure(OnceClosure read_closure) {
- EXPECT_TRUE(read_closure_.is_null());
- read_closure_ = std::move(read_closure);
- }
-
- void SetWriteClosure(OnceClosure write_closure) {
- EXPECT_TRUE(write_closure_.is_null());
- write_closure_ = std::move(write_closure);
- }
-
- // base:MessagePumpFuchsia::Watcher interface.
- void OnFileCanReadWithoutBlocking(int fd) override {
- // Empty the pipe buffer to reset the event. Otherwise libevent
- // implementation of MessageLoop may call the event handler again even if
- // |read_closure_| below quits the RunLoop.
- char c;
- int result = HANDLE_EINTR(read(fd, &c, 1));
- if (result == -1) {
- PLOG(ERROR) << "read";
- FAIL();
- }
- EXPECT_EQ(result, 1);
-
- ASSERT_FALSE(read_closure_.is_null());
- std::move(read_closure_).Run();
- }
-
- void OnFileCanWriteWithoutBlocking(int fd) override {
- ASSERT_FALSE(write_closure_.is_null());
- std::move(write_closure_).Run();
- }
-
- private:
- OnceClosure read_closure_;
- OnceClosure write_closure_;
-};
-
-TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherOutlivesMessageLoop) {
- // Simulate a MessageLoop that dies before an FileDescriptorWatcher.
- // This could happen when people use the Singleton pattern or atexit.
-
- // Arrange for watcher to live longer than message loop.
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
- TestHandler handler;
- {
- MessageLoopForIO message_loop;
-
- MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
- &handler);
- // Don't run the message loop, just destroy it.
- }
-
- ASSERT_FALSE(handler.is_readable_);
- ASSERT_FALSE(handler.is_writable_);
-}
-
-TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherDoubleStop) {
- // Verify that it's ok to call StopWatchingFileDescriptor().
-
- // Arrange for message loop to live longer than watcher.
- MessageLoopForIO message_loop;
- {
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
-
- TestHandler handler;
- MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE, &watcher,
- &handler);
- ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
- ASSERT_TRUE(watcher.StopWatchingFileDescriptor());
- }
-}
-
-TEST_F(MessageLoopForIoPosixTest, FileDescriptorWatcherDeleteInCallback) {
- // Verify that it is OK to delete the FileDescriptorWatcher from within a
- // callback.
- MessageLoopForIO message_loop;
-
- TestHandler handler;
- handler.watcher_to_delete_ =
- std::make_unique<MessagePumpForIO::FdWatchController>(FROM_HERE);
-
- MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- write_fd_.get(), true, MessagePumpForIO::WATCH_WRITE,
- handler.watcher_to_delete_.get(), &handler);
- RunLoop().Run();
-}
-
-// Verify that basic readable notification works.
-TEST_F(MessageLoopForIoPosixTest, WatchReadable) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
- TestHandler handler;
-
- // Watch the pipe for readability.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- // The pipe should not be readable when first created.
- RunLoop().RunUntilIdle();
- ASSERT_FALSE(handler.is_readable_);
- ASSERT_FALSE(handler.is_writable_);
-
- TriggerReadEvent();
-
- // We don't want to assume that the read fd becomes readable the
- // instant a bytes is written, so Run until quit by an event.
- RunLoop().Run();
-
- ASSERT_TRUE(handler.is_readable_);
- ASSERT_FALSE(handler.is_writable_);
-}
-
-// Verify that watching a file descriptor for writability succeeds.
-TEST_F(MessageLoopForIoPosixTest, WatchWritable) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
- TestHandler handler;
-
- // Watch the pipe for writability.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- write_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_WRITE,
- &watcher, &handler));
-
- // We should not receive a writable notification until we process events.
- ASSERT_FALSE(handler.is_readable_);
- ASSERT_FALSE(handler.is_writable_);
-
- // The pipe should be writable immediately, but wait for the quit closure
- // anyway, to be sure.
- RunLoop().Run();
-
- ASSERT_FALSE(handler.is_readable_);
- ASSERT_TRUE(handler.is_writable_);
-}
-
-// Verify that RunUntilIdle() receives IO notifications.
-TEST_F(MessageLoopForIoPosixTest, RunUntilIdle) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
- TestHandler handler;
-
- // Watch the pipe for readability.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- // The pipe should not be readable when first created.
- RunLoop().RunUntilIdle();
- ASSERT_FALSE(handler.is_readable_);
-
- TriggerReadEvent();
-
- while (!handler.is_readable_)
- RunLoop().RunUntilIdle();
-}
-
-void StopWatching(MessagePumpForIO::FdWatchController* controller,
- RunLoop* run_loop) {
- controller->StopWatchingFileDescriptor();
- run_loop->Quit();
-}
-
-// Verify that StopWatchingFileDescriptor() works from an event handler.
-TEST_F(MessageLoopForIoPosixTest, StopFromHandler) {
- MessageLoopForIO message_loop;
- RunLoop run_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
- CallClosureHandler handler(BindOnce(&StopWatching, &watcher, &run_loop),
- OnceClosure());
-
- // Create persistent watcher.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- TriggerReadEvent();
- run_loop.Run();
-
- // Trigger the event again. The event handler should not be called again.
- TriggerReadEvent();
- RunLoop().RunUntilIdle();
-}
-
-// Verify that non-persistent watcher is called only once.
-TEST_F(MessageLoopForIoPosixTest, NonPersistentWatcher) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
-
- RunLoop run_loop;
- CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
-
- // Create a non-persistent watcher.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- TriggerReadEvent();
- run_loop.Run();
-
- // Trigger the event again. handler should not be called again.
- TriggerReadEvent();
- RunLoop().RunUntilIdle();
-}
-
-// Verify that persistent watcher is called every time the event is triggered.
-TEST_F(MessageLoopForIoPosixTest, PersistentWatcher) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
-
- RunLoop run_loop1;
- CallClosureHandler handler(run_loop1.QuitClosure(), OnceClosure());
-
- // Create persistent watcher.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- TriggerReadEvent();
- run_loop1.Run();
-
- RunLoop run_loop2;
- handler.SetReadClosure(run_loop2.QuitClosure());
-
- // Trigger the event again. handler should be called now, which will quit
- // run_loop2.
- TriggerReadEvent();
- run_loop2.Run();
-}
-
-void StopWatchingAndWatchAgain(MessagePumpForIO::FdWatchController* controller,
- int fd,
- MessagePumpForIO::FdWatcher* new_handler,
- RunLoop* run_loop) {
- controller->StopWatchingFileDescriptor();
-
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- fd, /*persistent=*/true, MessagePumpForIO::WATCH_READ, controller,
- new_handler));
-
- run_loop->Quit();
-}
-
-// Verify that a watcher can be stopped and reused from an event handler.
-TEST_F(MessageLoopForIoPosixTest, StopAndRestartFromHandler) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
-
- RunLoop run_loop1;
- RunLoop run_loop2;
- CallClosureHandler handler2(run_loop2.QuitClosure(), OnceClosure());
- CallClosureHandler handler1(BindOnce(&StopWatchingAndWatchAgain, &watcher,
- read_fd_.get(), &handler2, &run_loop1),
- OnceClosure());
-
- // Create persistent watcher.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/true, MessagePumpForIO::WATCH_READ,
- &watcher, &handler1));
-
- TriggerReadEvent();
- run_loop1.Run();
-
- // Trigger the event again. handler2 should be called now, which will quit
- // run_loop2
- TriggerReadEvent();
- run_loop2.Run();
-}
-
-// Verify that the pump properly handles a delayed task after an IO event.
-TEST_F(MessageLoopForIoPosixTest, IoEventThenTimer) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
-
- RunLoop timer_run_loop;
- message_loop.task_runner()->PostDelayedTask(
- FROM_HERE, timer_run_loop.QuitClosure(),
- base::TimeDelta::FromMilliseconds(10));
-
- RunLoop watcher_run_loop;
- CallClosureHandler handler(watcher_run_loop.QuitClosure(), OnceClosure());
-
- // Create a non-persistent watcher.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- TriggerReadEvent();
-
- // Normally the IO event will be received before the delayed task is
- // executed, so this run loop will first handle the IO event and then quit on
- // the timer.
- timer_run_loop.Run();
-
- // Run watcher_run_loop in case the IO event wasn't received before the
- // delayed task.
- watcher_run_loop.Run();
-}
-
-// Verify that the pipe can handle an IO event after a delayed task.
-TEST_F(MessageLoopForIoPosixTest, TimerThenIoEvent) {
- MessageLoopForIO message_loop;
- MessagePumpForIO::FdWatchController watcher(FROM_HERE);
-
- // Trigger read event from a delayed task.
- message_loop.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&MessageLoopForIoPosixTest::TriggerReadEvent, Unretained(this)),
- TimeDelta::FromMilliseconds(1));
-
- RunLoop run_loop;
- CallClosureHandler handler(run_loop.QuitClosure(), OnceClosure());
-
- // Create a non-persistent watcher.
- ASSERT_TRUE(MessageLoopCurrentForIO::Get()->WatchFileDescriptor(
- read_fd_.get(), /*persistent=*/false, MessagePumpForIO::WATCH_READ,
- &watcher, &handler));
-
- run_loop.Run();
-}
-
-} // namespace
-
-#endif // !defined(OS_NACL)
-
-} // namespace base
diff --git a/base/message_loop/message_loop_task_runner_unittest.cc b/base/message_loop/message_loop_task_runner_unittest.cc
deleted file mode 100644
index c7e9aa0..0000000
--- a/base/message_loop/message_loop_task_runner_unittest.cc
+++ /dev/null
@@ -1,365 +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_loop_task_runner.h"
-
-#include <memory>
-
-#include "base/atomic_sequence_num.h"
-#include "base/bind.h"
-#include "base/debug/leak_annotations.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_task_runner.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace base {
-
-class MessageLoopTaskRunnerTest : public testing::Test {
- public:
- MessageLoopTaskRunnerTest()
- : current_loop_(new MessageLoop()),
- task_thread_("task_thread"),
- thread_sync_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- void DeleteCurrentMessageLoop() { current_loop_.reset(); }
-
- protected:
- void SetUp() override {
- // Use SetUp() instead of the constructor to avoid posting a task to a
- // partially constructed object.
- task_thread_.Start();
-
- // Allow us to pause the |task_thread_|'s MessageLoop.
- task_thread_.task_runner()->PostTask(
- FROM_HERE, BindOnce(&MessageLoopTaskRunnerTest::BlockTaskThreadHelper,
- Unretained(this)));
- }
-
- void TearDown() override {
- // Make sure the |task_thread_| is not blocked, and stop the thread
- // fully before destruction because its tasks may still depend on the
- // |thread_sync_| event.
- thread_sync_.Signal();
- task_thread_.Stop();
- DeleteCurrentMessageLoop();
- }
-
- // Make LoopRecorder threadsafe so that there is defined behavior even if a
- // threading mistake sneaks into the PostTaskAndReplyRelay implementation.
- class LoopRecorder : public RefCountedThreadSafe<LoopRecorder> {
- public:
- LoopRecorder(MessageLoop** run_on,
- MessageLoop** deleted_on,
- int* destruct_order)
- : run_on_(run_on),
- deleted_on_(deleted_on),
- destruct_order_(destruct_order) {}
-
- void RecordRun() { *run_on_ = MessageLoop::current(); }
-
- private:
- friend class RefCountedThreadSafe<LoopRecorder>;
- ~LoopRecorder() {
- *deleted_on_ = MessageLoop::current();
- *destruct_order_ = g_order.GetNext();
- }
-
- MessageLoop** run_on_;
- MessageLoop** deleted_on_;
- int* destruct_order_;
- };
-
- static void RecordLoop(scoped_refptr<LoopRecorder> recorder) {
- recorder->RecordRun();
- }
-
- static void RecordLoopAndQuit(scoped_refptr<LoopRecorder> recorder) {
- recorder->RecordRun();
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-
- void UnblockTaskThread() { thread_sync_.Signal(); }
-
- void BlockTaskThreadHelper() { thread_sync_.Wait(); }
-
- static AtomicSequenceNumber g_order;
-
- std::unique_ptr<MessageLoop> current_loop_;
- Thread task_thread_;
-
- private:
- base::WaitableEvent thread_sync_;
-};
-
-AtomicSequenceNumber MessageLoopTaskRunnerTest::g_order;
-
-TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_Basic) {
- MessageLoop* task_run_on = nullptr;
- MessageLoop* task_deleted_on = nullptr;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = nullptr;
- MessageLoop* reply_deleted_on = nullptr;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recorder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recorder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- ASSERT_TRUE(task_thread_.task_runner()->PostTaskAndReply(
- FROM_HERE, BindOnce(&RecordLoop, task_recorder),
- BindOnce(&RecordLoopAndQuit, reply_recorder)));
-
- // Die if base::Bind doesn't retain a reference to the recorders.
- task_recorder = nullptr;
- reply_recorder = nullptr;
- ASSERT_FALSE(task_deleted_on);
- ASSERT_FALSE(reply_deleted_on);
-
- UnblockTaskThread();
- RunLoop().Run();
-
- EXPECT_EQ(task_thread_.message_loop(), task_run_on);
- EXPECT_EQ(task_thread_.message_loop(), task_deleted_on);
- EXPECT_EQ(current_loop_.get(), reply_run_on);
- EXPECT_EQ(current_loop_.get(), reply_deleted_on);
- EXPECT_LT(task_delete_order, reply_delete_order);
-}
-
-TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReplyOnDeletedThreadDoesNotLeak) {
- MessageLoop* task_run_on = nullptr;
- MessageLoop* task_deleted_on = nullptr;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = nullptr;
- MessageLoop* reply_deleted_on = nullptr;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recorder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recorder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- // Grab a task runner to a dead MessageLoop.
- scoped_refptr<SingleThreadTaskRunner> task_runner =
- task_thread_.task_runner();
- UnblockTaskThread();
- task_thread_.Stop();
-
- ASSERT_FALSE(task_runner->PostTaskAndReply(
- FROM_HERE, BindOnce(&RecordLoop, task_recorder),
- BindOnce(&RecordLoopAndQuit, reply_recorder)));
-
- // The relay should have properly deleted its resources leaving us as the only
- // reference.
- EXPECT_EQ(task_delete_order, reply_delete_order);
- ASSERT_TRUE(task_recorder->HasOneRef());
- ASSERT_TRUE(reply_recorder->HasOneRef());
-
- // Nothing should have run though.
- EXPECT_FALSE(task_run_on);
- EXPECT_FALSE(reply_run_on);
-}
-
-TEST_F(MessageLoopTaskRunnerTest, PostTaskAndReply_SameLoop) {
- MessageLoop* task_run_on = nullptr;
- MessageLoop* task_deleted_on = nullptr;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = nullptr;
- MessageLoop* reply_deleted_on = nullptr;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recorder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recorder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- // Enqueue the relay.
- ASSERT_TRUE(current_loop_->task_runner()->PostTaskAndReply(
- FROM_HERE, BindOnce(&RecordLoop, task_recorder),
- BindOnce(&RecordLoopAndQuit, reply_recorder)));
-
- // Die if base::Bind doesn't retain a reference to the recorders.
- task_recorder = nullptr;
- reply_recorder = nullptr;
- ASSERT_FALSE(task_deleted_on);
- ASSERT_FALSE(reply_deleted_on);
-
- RunLoop().Run();
-
- EXPECT_EQ(current_loop_.get(), task_run_on);
- EXPECT_EQ(current_loop_.get(), task_deleted_on);
- EXPECT_EQ(current_loop_.get(), reply_run_on);
- EXPECT_EQ(current_loop_.get(), reply_deleted_on);
- EXPECT_LT(task_delete_order, reply_delete_order);
-}
-
-TEST_F(MessageLoopTaskRunnerTest,
- PostTaskAndReply_DeadReplyTaskRunnerBehavior) {
- // Annotate the scope as having memory leaks to suppress heapchecker reports.
- ANNOTATE_SCOPED_MEMORY_LEAK;
- MessageLoop* task_run_on = nullptr;
- MessageLoop* task_deleted_on = nullptr;
- int task_delete_order = -1;
- MessageLoop* reply_run_on = nullptr;
- MessageLoop* reply_deleted_on = nullptr;
- int reply_delete_order = -1;
-
- scoped_refptr<LoopRecorder> task_recorder =
- new LoopRecorder(&task_run_on, &task_deleted_on, &task_delete_order);
- scoped_refptr<LoopRecorder> reply_recorder =
- new LoopRecorder(&reply_run_on, &reply_deleted_on, &reply_delete_order);
-
- // Enqueue the relay.
- task_thread_.task_runner()->PostTaskAndReply(
- FROM_HERE, BindOnce(&RecordLoop, task_recorder),
- BindOnce(&RecordLoopAndQuit, reply_recorder));
-
- // Die if base::Bind doesn't retain a reference to the recorders.
- task_recorder = nullptr;
- reply_recorder = nullptr;
- ASSERT_FALSE(task_deleted_on);
- ASSERT_FALSE(reply_deleted_on);
-
- UnblockTaskThread();
-
- // Mercilessly whack the current loop before |reply| gets to run.
- current_loop_.reset();
-
- // This should ensure the relay has been run. We need to record the
- // MessageLoop pointer before stopping the thread because Thread::Stop() will
- // NULL out its own pointer.
- MessageLoop* task_loop = task_thread_.message_loop();
- task_thread_.Stop();
-
- // Even if the reply task runner is already gone, the original task should
- // already be deleted. However, the reply which hasn't executed yet should
- // leak to avoid thread-safety issues.
- EXPECT_EQ(task_loop, task_run_on);
- EXPECT_EQ(task_loop, task_deleted_on);
- EXPECT_FALSE(reply_run_on);
- ASSERT_FALSE(reply_deleted_on);
-
- // The PostTaskAndReplyRelay is leaked here. Even if we had a reference to
- // it, we cannot just delete it because PostTaskAndReplyRelay's destructor
- // checks that MessageLoop::current() is the the same as when the
- // PostTaskAndReplyRelay object was constructed. However, this loop must have
- // already been deleted in order to perform this test. See
- // http://crbug.com/86301.
-}
-
-class MessageLoopTaskRunnerThreadingTest : public testing::Test {
- public:
- void Release() const {
- AssertOnIOThread();
- Quit();
- }
-
- void Quit() const {
- loop_.task_runner()->PostTask(
- FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- }
-
- void AssertOnIOThread() const {
- ASSERT_TRUE(io_thread_->task_runner()->BelongsToCurrentThread());
- ASSERT_EQ(io_thread_->task_runner(), ThreadTaskRunnerHandle::Get());
- }
-
- void AssertOnFileThread() const {
- ASSERT_TRUE(file_thread_->task_runner()->BelongsToCurrentThread());
- ASSERT_EQ(file_thread_->task_runner(), ThreadTaskRunnerHandle::Get());
- }
-
- protected:
- void SetUp() override {
- io_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_IO"));
- file_thread_.reset(new Thread("MessageLoopTaskRunnerThreadingTest_File"));
- io_thread_->Start();
- file_thread_->Start();
- }
-
- void TearDown() override {
- io_thread_->Stop();
- file_thread_->Stop();
- }
-
- static void BasicFunction(MessageLoopTaskRunnerThreadingTest* test) {
- test->AssertOnFileThread();
- test->Quit();
- }
-
- static void AssertNotRun() { FAIL() << "Callback Should not get executed."; }
-
- class DeletedOnFile {
- public:
- explicit DeletedOnFile(MessageLoopTaskRunnerThreadingTest* test)
- : test_(test) {}
-
- ~DeletedOnFile() {
- test_->AssertOnFileThread();
- test_->Quit();
- }
-
- private:
- MessageLoopTaskRunnerThreadingTest* test_;
- };
-
- std::unique_ptr<Thread> io_thread_;
- std::unique_ptr<Thread> file_thread_;
-
- private:
- mutable MessageLoop loop_;
-};
-
-TEST_F(MessageLoopTaskRunnerThreadingTest, Release) {
- EXPECT_TRUE(io_thread_->task_runner()->ReleaseSoon(FROM_HERE, this));
- RunLoop().Run();
-}
-
-TEST_F(MessageLoopTaskRunnerThreadingTest, Delete) {
- DeletedOnFile* deleted_on_file = new DeletedOnFile(this);
- EXPECT_TRUE(
- file_thread_->task_runner()->DeleteSoon(FROM_HERE, deleted_on_file));
- RunLoop().Run();
-}
-
-TEST_F(MessageLoopTaskRunnerThreadingTest, PostTask) {
- EXPECT_TRUE(file_thread_->task_runner()->PostTask(
- FROM_HERE, BindOnce(&MessageLoopTaskRunnerThreadingTest::BasicFunction,
- Unretained(this))));
- RunLoop().Run();
-}
-
-TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadExits) {
- std::unique_ptr<Thread> test_thread(
- new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
- test_thread->Start();
- scoped_refptr<SingleThreadTaskRunner> task_runner =
- test_thread->task_runner();
- test_thread->Stop();
-
- bool ret = task_runner->PostTask(
- FROM_HERE, BindOnce(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
- EXPECT_FALSE(ret);
-}
-
-TEST_F(MessageLoopTaskRunnerThreadingTest, PostTaskAfterThreadIsDeleted) {
- scoped_refptr<SingleThreadTaskRunner> task_runner;
- {
- std::unique_ptr<Thread> test_thread(
- new Thread("MessageLoopTaskRunnerThreadingTest_Dummy"));
- test_thread->Start();
- task_runner = test_thread->task_runner();
- }
- bool ret = task_runner->PostTask(
- FROM_HERE, BindOnce(&MessageLoopTaskRunnerThreadingTest::AssertNotRun));
- EXPECT_FALSE(ret);
-}
-
-} // namespace base
diff --git a/base/message_loop/message_loop_unittest.cc b/base/message_loop/message_loop_unittest.cc
deleted file mode 100644
index 970f6d1..0000000
--- a/base/message_loop/message_loop_unittest.cc
+++ /dev/null
@@ -1,2184 +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 <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/compiler_specific.h"
-#include "base/logging.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/message_loop/message_pump_for_io.h"
-#include "base/pending_task.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/task_scheduler/task_scheduler.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequence_local_storage_slot.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#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"
-#endif
-
-#if defined(OS_WIN)
-#include "base/message_loop/message_pump_win.h"
-#include "base/process/memory.h"
-#include "base/strings/string16.h"
-#include "base/win/current_module.h"
-#include "base/win/scoped_handle.h"
-#endif
-
-namespace base {
-
-// TODO(darin): Platform-specific MessageLoop tests should be grouped together
-// to avoid chopping this file up with so many #ifdefs.
-
-namespace {
-
-class Foo : public RefCounted<Foo> {
- public:
- Foo() : test_count_(0) {
- }
-
- void Test0() { ++test_count_; }
-
- void Test1ConstRef(const std::string& a) {
- ++test_count_;
- result_.append(a);
- }
-
- void Test1Ptr(std::string* a) {
- ++test_count_;
- result_.append(*a);
- }
-
- void Test1Int(int a) { test_count_ += a; }
-
- void Test2Ptr(std::string* a, std::string* b) {
- ++test_count_;
- result_.append(*a);
- result_.append(*b);
- }
-
- void Test2Mixed(const std::string& a, std::string* b) {
- ++test_count_;
- result_.append(a);
- result_.append(*b);
- }
-
- int test_count() const { return test_count_; }
- const std::string& result() const { return result_; }
-
- private:
- friend class RefCounted<Foo>;
-
- ~Foo() = default;
-
- int test_count_;
- std::string result_;
-
- DISALLOW_COPY_AND_ASSIGN(Foo);
-};
-
-// This function runs slowly to simulate a large amount of work being done.
-static void SlowFunc(TimeDelta pause, int* quit_counter) {
- PlatformThread::Sleep(pause);
- if (--(*quit_counter) == 0)
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-// This function records the time when Run was called in a Time object, which is
-// useful for building a variety of MessageLoop tests.
-static void RecordRunTimeFunc(TimeTicks* run_time, int* quit_counter) {
- *run_time = TimeTicks::Now();
-
- // Cause our Run function to take some time to execute. As a result we can
- // count on subsequent RecordRunTimeFunc()s running at a future time,
- // without worry about the resolution of our system clock being an issue.
- SlowFunc(TimeDelta::FromMilliseconds(10), quit_counter);
-}
-
-enum TaskType {
- MESSAGEBOX,
- ENDDIALOG,
- RECURSIVE,
- TIMEDMESSAGELOOP,
- QUITMESSAGELOOP,
- ORDERED,
- PUMPS,
- SLEEP,
- RUNS,
-};
-
-// Saves the order in which the tasks executed.
-struct TaskItem {
- TaskItem(TaskType t, int c, bool s)
- : type(t),
- cookie(c),
- start(s) {
- }
-
- TaskType type;
- int cookie;
- bool start;
-
- bool operator == (const TaskItem& other) const {
- return type == other.type && cookie == other.cookie && start == other.start;
- }
-};
-
-std::ostream& operator <<(std::ostream& os, TaskType type) {
- switch (type) {
- case MESSAGEBOX: os << "MESSAGEBOX"; break;
- case ENDDIALOG: os << "ENDDIALOG"; break;
- case RECURSIVE: os << "RECURSIVE"; break;
- case TIMEDMESSAGELOOP: os << "TIMEDMESSAGELOOP"; break;
- case QUITMESSAGELOOP: os << "QUITMESSAGELOOP"; break;
- case ORDERED: os << "ORDERED"; break;
- case PUMPS: os << "PUMPS"; break;
- case SLEEP: os << "SLEEP"; break;
- default:
- NOTREACHED();
- os << "Unknown TaskType";
- break;
- }
- return os;
-}
-
-std::ostream& operator <<(std::ostream& os, const TaskItem& item) {
- if (item.start)
- return os << item.type << " " << item.cookie << " starts";
- else
- return os << item.type << " " << item.cookie << " ends";
-}
-
-class TaskList {
- public:
- void RecordStart(TaskType type, int cookie) {
- TaskItem item(type, cookie, true);
- DVLOG(1) << item;
- task_list_.push_back(item);
- }
-
- void RecordEnd(TaskType type, int cookie) {
- TaskItem item(type, cookie, false);
- DVLOG(1) << item;
- task_list_.push_back(item);
- }
-
- size_t Size() {
- return task_list_.size();
- }
-
- TaskItem Get(int n) {
- return task_list_[n];
- }
-
- private:
- std::vector<TaskItem> task_list_;
-};
-
-class DummyTaskObserver : public MessageLoop::TaskObserver {
- public:
- explicit DummyTaskObserver(int num_tasks)
- : num_tasks_started_(0), num_tasks_processed_(0), num_tasks_(num_tasks) {}
-
- DummyTaskObserver(int num_tasks, int num_tasks_started)
- : num_tasks_started_(num_tasks_started),
- num_tasks_processed_(0),
- num_tasks_(num_tasks) {}
-
- ~DummyTaskObserver() override = default;
-
- void WillProcessTask(const PendingTask& pending_task) override {
- num_tasks_started_++;
- EXPECT_LE(num_tasks_started_, num_tasks_);
- EXPECT_EQ(num_tasks_started_, num_tasks_processed_ + 1);
- }
-
- void DidProcessTask(const PendingTask& pending_task) override {
- num_tasks_processed_++;
- EXPECT_LE(num_tasks_started_, num_tasks_);
- EXPECT_EQ(num_tasks_started_, num_tasks_processed_);
- }
-
- int num_tasks_started() const { return num_tasks_started_; }
- int num_tasks_processed() const { return num_tasks_processed_; }
-
- private:
- int num_tasks_started_;
- int num_tasks_processed_;
- const int num_tasks_;
-
- DISALLOW_COPY_AND_ASSIGN(DummyTaskObserver);
-};
-
-void RecursiveFunc(TaskList* order, int cookie, int depth,
- bool is_reentrant) {
- order->RecordStart(RECURSIVE, cookie);
- if (depth > 0) {
- if (is_reentrant)
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&RecursiveFunc, order, cookie, depth - 1, is_reentrant));
- }
- order->RecordEnd(RECURSIVE, cookie);
-}
-
-void QuitFunc(TaskList* order, int cookie) {
- order->RecordStart(QUITMESSAGELOOP, cookie);
- RunLoop::QuitCurrentWhenIdleDeprecated();
- order->RecordEnd(QUITMESSAGELOOP, cookie);
-}
-
-void PostNTasks(int posts_remaining) {
- if (posts_remaining > 1) {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&PostNTasks, posts_remaining - 1));
- }
-}
-
-enum class TaskSchedulerAvailability {
- NO_TASK_SCHEDULER,
- WITH_TASK_SCHEDULER,
-};
-
-std::string TaskSchedulerAvailabilityToString(
- TaskSchedulerAvailability availability) {
- switch (availability) {
- case TaskSchedulerAvailability::NO_TASK_SCHEDULER:
- return "NoTaskScheduler";
- case TaskSchedulerAvailability::WITH_TASK_SCHEDULER:
- return "WithTaskScheduler";
- }
- NOTREACHED();
- return "Unknown";
-}
-
-class MessageLoopTest
- : public ::testing::TestWithParam<TaskSchedulerAvailability> {
- public:
- MessageLoopTest() = default;
- ~MessageLoopTest() override = default;
-
- void SetUp() override {
- if (GetParam() == TaskSchedulerAvailability::WITH_TASK_SCHEDULER)
- TaskScheduler::CreateAndStartWithDefaultParams("MessageLoopTest");
- }
-
- void TearDown() override {
- if (GetParam() == TaskSchedulerAvailability::WITH_TASK_SCHEDULER) {
- // Failure to call FlushForTesting() could result in task leaks as tasks
- // are skipped on shutdown.
- base::TaskScheduler::GetInstance()->FlushForTesting();
- base::TaskScheduler::GetInstance()->Shutdown();
- base::TaskScheduler::GetInstance()->JoinForTesting();
- base::TaskScheduler::SetInstance(nullptr);
- }
- }
-
- static std::string ParamInfoToString(
- ::testing::TestParamInfo<TaskSchedulerAvailability> param_info) {
- return TaskSchedulerAvailabilityToString(param_info.param);
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MessageLoopTest);
-};
-
-#if defined(OS_ANDROID)
-void DoNotRun() {
- ASSERT_TRUE(false);
-}
-
-void RunTest_AbortDontRunMoreTasks(bool delayed, bool init_java_first) {
- WaitableEvent test_done_event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- std::unique_ptr<android::JavaHandlerThread> java_thread;
- if (init_java_first) {
- java_thread = android::JavaHandlerThreadHelpers::CreateJavaFirst();
- } else {
- java_thread = std::make_unique<android::JavaHandlerThread>(
- "JavaHandlerThreadForTesting from AbortDontRunMoreTasks");
- }
- java_thread->Start();
- java_thread->ListenForUncaughtExceptionsForTesting();
-
- auto target =
- BindOnce(&android::JavaHandlerThreadHelpers::ThrowExceptionAndAbort,
- &test_done_event);
- if (delayed) {
- java_thread->message_loop()->task_runner()->PostDelayedTask(
- FROM_HERE, std::move(target), TimeDelta::FromMilliseconds(10));
- } else {
- java_thread->message_loop()->task_runner()->PostTask(FROM_HERE,
- std::move(target));
- java_thread->message_loop()->task_runner()->PostTask(FROM_HERE,
- BindOnce(&DoNotRun));
- }
- test_done_event.Wait();
- java_thread->Stop();
- android::ScopedJavaLocalRef<jthrowable> exception =
- java_thread->GetUncaughtExceptionIfAny();
- ASSERT_TRUE(
- android::JavaHandlerThreadHelpers::IsExceptionTestException(exception));
-}
-
-TEST_P(MessageLoopTest, JavaExceptionAbort) {
- constexpr bool delayed = false;
- constexpr bool init_java_first = false;
- RunTest_AbortDontRunMoreTasks(delayed, init_java_first);
-}
-TEST_P(MessageLoopTest, DelayedJavaExceptionAbort) {
- constexpr bool delayed = true;
- constexpr bool init_java_first = false;
- RunTest_AbortDontRunMoreTasks(delayed, init_java_first);
-}
-TEST_P(MessageLoopTest, JavaExceptionAbortInitJavaFirst) {
- constexpr bool delayed = false;
- constexpr bool init_java_first = true;
- RunTest_AbortDontRunMoreTasks(delayed, init_java_first);
-}
-
-TEST_P(MessageLoopTest, RunTasksWhileShuttingDownJavaThread) {
- const int kNumPosts = 6;
- DummyTaskObserver observer(kNumPosts, 1);
-
- auto java_thread = std::make_unique<android::JavaHandlerThread>("test");
- java_thread->Start();
-
- java_thread->message_loop()->task_runner()->PostTask(
- FROM_HERE,
- BindOnce(
- [](android::JavaHandlerThread* java_thread,
- DummyTaskObserver* observer, int num_posts) {
- java_thread->message_loop()->AddTaskObserver(observer);
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce([]() { ADD_FAILURE(); }),
- TimeDelta::FromDays(1));
- java_thread->StopMessageLoopForTesting();
- PostNTasks(num_posts);
- },
- Unretained(java_thread.get()), Unretained(&observer), kNumPosts));
-
- java_thread->JoinForTesting();
- java_thread.reset();
-
- EXPECT_EQ(kNumPosts, observer.num_tasks_started());
- EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
-}
-#endif // defined(OS_ANDROID)
-
-#if defined(OS_WIN)
-
-void SubPumpFunc() {
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- MSG msg;
- while (GetMessage(&msg, NULL, 0, 0)) {
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-void RunTest_PostDelayedTask_SharedTimer_SubPump() {
- MessageLoop message_loop(MessageLoop::TYPE_UI);
-
- // Test that the interval of the timer, used to run the next delayed task, is
- // set to a value corresponding to when the next delayed task should run.
-
- // By setting num_tasks to 1, we ensure that the first task to run causes the
- // run loop to exit.
- int num_tasks = 1;
- TimeTicks run_time;
-
- message_loop.task_runner()->PostTask(FROM_HERE, BindOnce(&SubPumpFunc));
-
- // This very delayed task should never run.
- message_loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks),
- TimeDelta::FromSeconds(1000));
-
- // This slightly delayed task should run from within SubPumpFunc.
- message_loop.task_runner()->PostDelayedTask(FROM_HERE,
- BindOnce(&PostQuitMessage, 0),
- TimeDelta::FromMilliseconds(10));
-
- Time start_time = Time::Now();
-
- RunLoop().Run();
- EXPECT_EQ(1, num_tasks);
-
- // Ensure that we ran in far less time than the slower timer.
- TimeDelta total_time = Time::Now() - start_time;
- EXPECT_GT(5000, total_time.InMilliseconds());
-
- // In case both timers somehow run at nearly the same time, sleep a little
- // and then run all pending to force them both to have run. This is just
- // encouraging flakiness if there is any.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
- RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(run_time.is_null());
-}
-
-const wchar_t kMessageBoxTitle[] = L"MessageLoop Unit Test";
-
-// MessageLoop implicitly start a "modal message loop". Modal dialog boxes,
-// common controls (like OpenFile) and StartDoc printing function can cause
-// implicit message loops.
-void MessageBoxFunc(TaskList* order, int cookie, bool is_reentrant) {
- order->RecordStart(MESSAGEBOX, cookie);
- if (is_reentrant)
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- MessageBox(NULL, L"Please wait...", kMessageBoxTitle, MB_OK);
- order->RecordEnd(MESSAGEBOX, cookie);
-}
-
-// Will end the MessageBox.
-void EndDialogFunc(TaskList* order, int cookie) {
- order->RecordStart(ENDDIALOG, cookie);
- HWND window = GetActiveWindow();
- if (window != NULL) {
- EXPECT_NE(EndDialog(window, IDCONTINUE), 0);
- // Cheap way to signal that the window wasn't found if RunEnd() isn't
- // called.
- order->RecordEnd(ENDDIALOG, cookie);
- }
-}
-
-void RecursiveFuncWin(scoped_refptr<SingleThreadTaskRunner> task_runner,
- HANDLE event,
- bool expect_window,
- TaskList* order,
- bool is_reentrant) {
- task_runner->PostTask(FROM_HERE,
- BindOnce(&RecursiveFunc, order, 1, 2, is_reentrant));
- task_runner->PostTask(FROM_HERE,
- BindOnce(&MessageBoxFunc, order, 2, is_reentrant));
- task_runner->PostTask(FROM_HERE,
- BindOnce(&RecursiveFunc, order, 3, 2, is_reentrant));
- // The trick here is that for recursive task processing, this task will be
- // ran _inside_ the MessageBox message loop, dismissing the MessageBox
- // without a chance.
- // For non-recursive task processing, this will be executed _after_ the
- // MessageBox will have been dismissed by the code below, where
- // expect_window_ is true.
- task_runner->PostTask(FROM_HERE, BindOnce(&EndDialogFunc, order, 4));
- task_runner->PostTask(FROM_HERE, BindOnce(&QuitFunc, order, 5));
-
- // Enforce that every tasks are sent before starting to run the main thread
- // message loop.
- ASSERT_TRUE(SetEvent(event));
-
- // Poll for the MessageBox. Don't do this at home! At the speed we do it,
- // you will never realize one MessageBox was shown.
- for (; expect_window;) {
- HWND window = FindWindow(L"#32770", kMessageBoxTitle);
- if (window) {
- // Dismiss it.
- for (;;) {
- HWND button = FindWindowEx(window, NULL, L"Button", NULL);
- if (button != NULL) {
- EXPECT_EQ(0, SendMessage(button, WM_LBUTTONDOWN, 0, 0));
- EXPECT_EQ(0, SendMessage(button, WM_LBUTTONUP, 0, 0));
- break;
- }
- }
- break;
- }
- }
-}
-
-// TODO(darin): These tests need to be ported since they test critical
-// message loop functionality.
-
-// A side effect of this test is the generation a beep. Sorry.
-void RunTest_RecursiveDenial2(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- Thread worker("RecursiveDenial2_worker");
- Thread::Options options;
- options.message_loop_type = message_loop_type;
- ASSERT_EQ(true, worker.StartWithOptions(options));
- TaskList order;
- win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
- worker.task_runner()->PostTask(
- FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(),
- event.Get(), true, &order, false));
- // Let the other thread execute.
- WaitForSingleObject(event.Get(), INFINITE);
- RunLoop().Run();
-
- ASSERT_EQ(17u, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
- EXPECT_EQ(order.Get(3), TaskItem(MESSAGEBOX, 2, false));
- EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, true));
- EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 3, false));
- // When EndDialogFunc is processed, the window is already dismissed, hence no
- // "end" entry.
- EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, true));
- EXPECT_EQ(order.Get(7), TaskItem(QUITMESSAGELOOP, 5, true));
- EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, false));
- EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 3, true));
- EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, false));
- EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 3, true));
- EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, false));
-}
-
-// A side effect of this test is the generation a beep. Sorry. This test also
-// needs to process windows messages on the current thread.
-void RunTest_RecursiveSupport2(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- Thread worker("RecursiveSupport2_worker");
- Thread::Options options;
- options.message_loop_type = message_loop_type;
- ASSERT_EQ(true, worker.StartWithOptions(options));
- TaskList order;
- win::ScopedHandle event(CreateEvent(NULL, FALSE, FALSE, NULL));
- worker.task_runner()->PostTask(
- FROM_HERE, BindOnce(&RecursiveFuncWin, ThreadTaskRunnerHandle::Get(),
- event.Get(), false, &order, true));
- // Let the other thread execute.
- WaitForSingleObject(event.Get(), INFINITE);
- RunLoop().Run();
-
- ASSERT_EQ(18u, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(2), TaskItem(MESSAGEBOX, 2, true));
- // Note that this executes in the MessageBox modal loop.
- EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 3, true));
- EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 3, false));
- EXPECT_EQ(order.Get(5), TaskItem(ENDDIALOG, 4, true));
- EXPECT_EQ(order.Get(6), TaskItem(ENDDIALOG, 4, false));
- EXPECT_EQ(order.Get(7), TaskItem(MESSAGEBOX, 2, false));
- /* The order can subtly change here. The reason is that when RecursiveFunc(1)
- is called in the main thread, if it is faster than getting to the
- PostTask(FROM_HERE, BindOnce(&QuitFunc) execution, the order of task
- execution can change. We don't care anyway that the order isn't correct.
- EXPECT_EQ(order.Get(8), TaskItem(QUITMESSAGELOOP, 5, true));
- EXPECT_EQ(order.Get(9), TaskItem(QUITMESSAGELOOP, 5, false));
- EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
- */
- EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 3, true));
- EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 3, false));
- EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(16), TaskItem(RECURSIVE, 3, true));
- EXPECT_EQ(order.Get(17), TaskItem(RECURSIVE, 3, false));
-}
-
-#endif // defined(OS_WIN)
-
-void PostNTasksThenQuit(int posts_remaining) {
- if (posts_remaining > 1) {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&PostNTasksThenQuit, posts_remaining - 1));
- } else {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-}
-
-#if defined(OS_WIN)
-
-class TestIOHandler : public MessagePumpForIO::IOHandler {
- public:
- TestIOHandler(const wchar_t* name, HANDLE signal, bool wait);
-
- void OnIOCompleted(MessagePumpForIO::IOContext* context,
- DWORD bytes_transfered,
- DWORD error) override;
-
- void Init();
- void WaitForIO();
- OVERLAPPED* context() { return &context_.overlapped; }
- DWORD size() { return sizeof(buffer_); }
-
- private:
- char buffer_[48];
- MessagePumpForIO::IOContext context_;
- HANDLE signal_;
- win::ScopedHandle file_;
- bool wait_;
-};
-
-TestIOHandler::TestIOHandler(const wchar_t* name, HANDLE signal, bool wait)
- : signal_(signal), wait_(wait) {
- memset(buffer_, 0, sizeof(buffer_));
-
- file_.Set(CreateFile(name, GENERIC_READ, 0, NULL, OPEN_EXISTING,
- FILE_FLAG_OVERLAPPED, NULL));
- EXPECT_TRUE(file_.IsValid());
-}
-
-void TestIOHandler::Init() {
- MessageLoopCurrentForIO::Get()->RegisterIOHandler(file_.Get(), this);
-
- DWORD read;
- EXPECT_FALSE(ReadFile(file_.Get(), buffer_, size(), &read, context()));
- EXPECT_EQ(static_cast<DWORD>(ERROR_IO_PENDING), GetLastError());
- if (wait_)
- WaitForIO();
-}
-
-void TestIOHandler::OnIOCompleted(MessagePumpForIO::IOContext* context,
- DWORD bytes_transfered,
- DWORD error) {
- ASSERT_TRUE(context == &context_);
- ASSERT_TRUE(SetEvent(signal_));
-}
-
-void TestIOHandler::WaitForIO() {
- EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(300, this));
- EXPECT_TRUE(MessageLoopCurrentForIO::Get()->WaitForIOCompletion(400, this));
-}
-
-void RunTest_IOHandler() {
- win::ScopedHandle callback_called(CreateEvent(NULL, TRUE, FALSE, NULL));
- ASSERT_TRUE(callback_called.IsValid());
-
- const wchar_t* kPipeName = L"\\\\.\\pipe\\iohandler_pipe";
- win::ScopedHandle server(
- CreateNamedPipe(kPipeName, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
- ASSERT_TRUE(server.IsValid());
-
- Thread thread("IOHandler test");
- Thread::Options options;
- options.message_loop_type = MessageLoop::TYPE_IO;
- ASSERT_TRUE(thread.StartWithOptions(options));
-
- TestIOHandler handler(kPipeName, callback_called.Get(), false);
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler)));
- // Make sure the thread runs and sleeps for lack of work.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
-
- const char buffer[] = "Hello there!";
- DWORD written;
- EXPECT_TRUE(WriteFile(server.Get(), buffer, sizeof(buffer), &written, NULL));
-
- DWORD result = WaitForSingleObject(callback_called.Get(), 1000);
- EXPECT_EQ(WAIT_OBJECT_0, result);
-
- thread.Stop();
-}
-
-void RunTest_WaitForIO() {
- win::ScopedHandle callback1_called(
- CreateEvent(NULL, TRUE, FALSE, NULL));
- win::ScopedHandle callback2_called(
- CreateEvent(NULL, TRUE, FALSE, NULL));
- ASSERT_TRUE(callback1_called.IsValid());
- ASSERT_TRUE(callback2_called.IsValid());
-
- const wchar_t* kPipeName1 = L"\\\\.\\pipe\\iohandler_pipe1";
- const wchar_t* kPipeName2 = L"\\\\.\\pipe\\iohandler_pipe2";
- win::ScopedHandle server1(
- CreateNamedPipe(kPipeName1, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
- win::ScopedHandle server2(
- CreateNamedPipe(kPipeName2, PIPE_ACCESS_OUTBOUND, 0, 1, 0, 0, 0, NULL));
- ASSERT_TRUE(server1.IsValid());
- ASSERT_TRUE(server2.IsValid());
-
- Thread thread("IOHandler test");
- Thread::Options options;
- options.message_loop_type = MessageLoop::TYPE_IO;
- ASSERT_TRUE(thread.StartWithOptions(options));
-
- TestIOHandler handler1(kPipeName1, callback1_called.Get(), false);
- TestIOHandler handler2(kPipeName2, callback2_called.Get(), true);
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler1)));
- // TODO(ajwong): Do we really need such long Sleeps in this function?
- // Make sure the thread runs and sleeps for lack of work.
- TimeDelta delay = TimeDelta::FromMilliseconds(100);
- PlatformThread::Sleep(delay);
- thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&TestIOHandler::Init, Unretained(&handler2)));
- PlatformThread::Sleep(delay);
-
- // At this time handler1 is waiting to be called, and the thread is waiting
- // on the Init method of handler2, filtering only handler2 callbacks.
-
- const char buffer[] = "Hello there!";
- DWORD written;
- EXPECT_TRUE(WriteFile(server1.Get(), buffer, sizeof(buffer), &written, NULL));
- PlatformThread::Sleep(2 * delay);
- EXPECT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
- WaitForSingleObject(callback1_called.Get(), 0))
- << "handler1 has not been called";
-
- EXPECT_TRUE(WriteFile(server2.Get(), buffer, sizeof(buffer), &written, NULL));
-
- HANDLE objects[2] = { callback1_called.Get(), callback2_called.Get() };
- DWORD result = WaitForMultipleObjects(2, objects, TRUE, 1000);
- EXPECT_EQ(WAIT_OBJECT_0, result);
-
- thread.Stop();
-}
-
-#endif // defined(OS_WIN)
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-// Each test is run against each type of MessageLoop. That way we are sure
-// that message loops work properly in all configurations. Of course, in some
-// cases, a unit test may only be for a particular type of loop.
-
-namespace {
-
-struct MessageLoopTypedTestParams {
- MessageLoopTypedTestParams(
- MessageLoop::Type type_in,
- TaskSchedulerAvailability task_scheduler_availability_in) {
- type = type_in;
- task_scheduler_availability = task_scheduler_availability_in;
- }
-
- MessageLoop::Type type;
- TaskSchedulerAvailability task_scheduler_availability;
-};
-
-class MessageLoopTypedTest
- : public ::testing::TestWithParam<MessageLoopTypedTestParams> {
- public:
- MessageLoopTypedTest() = default;
- ~MessageLoopTypedTest() = default;
-
- void SetUp() override {
- if (GetTaskSchedulerAvailability() ==
- TaskSchedulerAvailability::WITH_TASK_SCHEDULER) {
- TaskScheduler::CreateAndStartWithDefaultParams("MessageLoopTypedTest");
- }
- }
-
- void TearDown() override {
- if (GetTaskSchedulerAvailability() ==
- TaskSchedulerAvailability::WITH_TASK_SCHEDULER) {
- // Failure to call FlushForTesting() could result in task leaks as tasks
- // are skipped on shutdown.
- base::TaskScheduler::GetInstance()->FlushForTesting();
- base::TaskScheduler::GetInstance()->Shutdown();
- base::TaskScheduler::GetInstance()->JoinForTesting();
- base::TaskScheduler::SetInstance(nullptr);
- }
- }
-
- static std::string ParamInfoToString(
- ::testing::TestParamInfo<MessageLoopTypedTestParams> param_info) {
- return MessageLoopTypeToString(param_info.param.type) + "_" +
- TaskSchedulerAvailabilityToString(
- param_info.param.task_scheduler_availability);
- }
-
- protected:
- MessageLoop::Type GetMessageLoopType() { return GetParam().type; }
-
- private:
- static std::string MessageLoopTypeToString(MessageLoop::Type type) {
- switch (type) {
- case MessageLoop::TYPE_DEFAULT:
- return "Default";
- case MessageLoop::TYPE_IO:
- return "IO";
- case MessageLoop::TYPE_UI:
- return "UI";
- case MessageLoop::TYPE_CUSTOM:
-#if defined(OS_ANDROID)
- case MessageLoop::TYPE_JAVA:
-#endif // defined(OS_ANDROID)
- break;
- }
- NOTREACHED();
- return "NotSupported";
- }
-
- TaskSchedulerAvailability GetTaskSchedulerAvailability() {
- return GetParam().task_scheduler_availability;
- }
-
- DISALLOW_COPY_AND_ASSIGN(MessageLoopTypedTest);
-};
-
-} // namespace
-
-TEST_P(MessageLoopTypedTest, PostTask) {
- MessageLoop loop(GetMessageLoopType());
- // Add tests to message loop
- scoped_refptr<Foo> foo(new Foo());
- std::string a("a"), b("b"), c("c"), d("d");
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&Foo::Test0, foo));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, a));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&Foo::Test1Ptr, foo, &b));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&Foo::Test1Int, foo, 100));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&Foo::Test2Ptr, foo, &a, &c));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&Foo::Test2Mixed, foo, a, &d));
- // After all tests, post a message that will shut down the message loop
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
-
- // Now kick things off
- RunLoop().Run();
-
- EXPECT_EQ(foo->test_count(), 105);
- EXPECT_EQ(foo->result(), "abacad");
-}
-
-TEST_P(MessageLoopTypedTest, PostDelayedTask_Basic) {
- MessageLoop loop(GetMessageLoopType());
-
- // Test that PostDelayedTask results in a delayed task.
-
- const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
-
- int num_tasks = 1;
- TimeTicks run_time;
-
- TimeTicks time_before_run = TimeTicks::Now();
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks), kDelay);
- RunLoop().Run();
- TimeTicks time_after_run = TimeTicks::Now();
-
- EXPECT_EQ(0, num_tasks);
- EXPECT_LT(kDelay, time_after_run - time_before_run);
-}
-
-TEST_P(MessageLoopTypedTest, PostDelayedTask_InDelayOrder) {
- MessageLoop loop(GetMessageLoopType());
-
- // Test that two tasks with different delays run in the right order.
- int num_tasks = 2;
- TimeTicks run_time1, run_time2;
-
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks),
- TimeDelta::FromMilliseconds(200));
- // If we get a large pause in execution (due to a context switch) here, this
- // test could fail.
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
- TimeDelta::FromMilliseconds(10));
-
- RunLoop().Run();
- EXPECT_EQ(0, num_tasks);
-
- EXPECT_TRUE(run_time2 < run_time1);
-}
-
-TEST_P(MessageLoopTypedTest, PostDelayedTask_InPostOrder) {
- MessageLoop loop(GetMessageLoopType());
-
- // Test that two tasks with the same delay 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.
-
- const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
-
- int num_tasks = 2;
- TimeTicks run_time1, run_time2;
-
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks), kDelay);
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks), kDelay);
-
- RunLoop().Run();
- EXPECT_EQ(0, num_tasks);
-
- EXPECT_TRUE(run_time1 < run_time2);
-}
-
-TEST_P(MessageLoopTypedTest, PostDelayedTask_InPostOrder_2) {
- MessageLoop loop(GetMessageLoopType());
-
- // Test that a delayed task still runs after a normal tasks even if the
- // normal tasks take a long time to run.
-
- const TimeDelta kPause = TimeDelta::FromMilliseconds(50);
-
- int num_tasks = 2;
- TimeTicks run_time;
-
- loop.task_runner()->PostTask(FROM_HERE,
- BindOnce(&SlowFunc, kPause, &num_tasks));
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time, &num_tasks),
- TimeDelta::FromMilliseconds(10));
-
- TimeTicks time_before_run = TimeTicks::Now();
- RunLoop().Run();
- TimeTicks time_after_run = TimeTicks::Now();
-
- EXPECT_EQ(0, num_tasks);
-
- EXPECT_LT(kPause, time_after_run - time_before_run);
-}
-
-TEST_P(MessageLoopTypedTest, PostDelayedTask_InPostOrder_3) {
- MessageLoop loop(GetMessageLoopType());
-
- // Test that a delayed task still runs after a pile of normal tasks. The key
- // difference between this test and the previous one is that here we return
- // the MessageLoop a lot so we give the MessageLoop plenty of opportunities
- // to maybe run the delayed task. It should know not to do so until the
- // delayed task's delay has passed.
-
- int num_tasks = 11;
- TimeTicks run_time1, run_time2;
-
- // Clutter the ML with tasks.
- for (int i = 1; i < num_tasks; ++i)
- loop.task_runner()->PostTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks));
-
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
- TimeDelta::FromMilliseconds(1));
-
- RunLoop().Run();
- EXPECT_EQ(0, num_tasks);
-
- EXPECT_TRUE(run_time2 > run_time1);
-}
-
-TEST_P(MessageLoopTypedTest, PostDelayedTask_SharedTimer) {
- MessageLoop loop(GetMessageLoopType());
-
- // Test that the interval of the timer, used to run the next delayed task, is
- // set to a value corresponding to when the next delayed task should run.
-
- // By setting num_tasks to 1, we ensure that the first task to run causes the
- // run loop to exit.
- int num_tasks = 1;
- TimeTicks run_time1, run_time2;
-
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time1, &num_tasks),
- TimeDelta::FromSeconds(1000));
- loop.task_runner()->PostDelayedTask(
- FROM_HERE, BindOnce(&RecordRunTimeFunc, &run_time2, &num_tasks),
- TimeDelta::FromMilliseconds(10));
-
- TimeTicks start_time = TimeTicks::Now();
-
- RunLoop().Run();
- EXPECT_EQ(0, num_tasks);
-
- // Ensure that we ran in far less time than the slower timer.
- TimeDelta total_time = TimeTicks::Now() - start_time;
- EXPECT_GT(5000, total_time.InMilliseconds());
-
- // In case both timers somehow run at nearly the same time, sleep a little
- // and then run all pending to force them both to have run. This is just
- // encouraging flakiness if there is any.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
- RunLoop().RunUntilIdle();
-
- EXPECT_TRUE(run_time1.is_null());
- EXPECT_FALSE(run_time2.is_null());
-}
-
-namespace {
-
-// This is used to inject a test point for recording the destructor calls for
-// Closure objects send to MessageLoop::PostTask(). It is awkward usage since we
-// are trying to hook the actual destruction, which is not a common operation.
-class RecordDeletionProbe : public RefCounted<RecordDeletionProbe> {
- public:
- RecordDeletionProbe(RecordDeletionProbe* post_on_delete, bool* was_deleted)
- : post_on_delete_(post_on_delete), was_deleted_(was_deleted) {}
- void Run() {}
-
- private:
- friend class RefCounted<RecordDeletionProbe>;
-
- ~RecordDeletionProbe() {
- *was_deleted_ = true;
- if (post_on_delete_.get())
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecordDeletionProbe::Run, post_on_delete_));
- }
-
- scoped_refptr<RecordDeletionProbe> post_on_delete_;
- bool* was_deleted_;
-};
-
-} // namespace
-
-/* TODO(darin): MessageLoop does not support deleting all tasks in the */
-/* destructor. */
-/* Fails, http://crbug.com/50272. */
-TEST_P(MessageLoopTypedTest, DISABLED_EnsureDeletion) {
- bool a_was_deleted = false;
- bool b_was_deleted = false;
- {
- MessageLoop loop(GetMessageLoopType());
- loop.task_runner()->PostTask(
- FROM_HERE, BindOnce(&RecordDeletionProbe::Run,
- new RecordDeletionProbe(nullptr, &a_was_deleted)));
- // TODO(ajwong): Do we really need 1000ms here?
- loop.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&RecordDeletionProbe::Run,
- new RecordDeletionProbe(nullptr, &b_was_deleted)),
- TimeDelta::FromMilliseconds(1000));
- }
- EXPECT_TRUE(a_was_deleted);
- EXPECT_TRUE(b_was_deleted);
-}
-
-/* TODO(darin): MessageLoop does not support deleting all tasks in the */
-/* destructor. */
-/* Fails, http://crbug.com/50272. */
-TEST_P(MessageLoopTypedTest, DISABLED_EnsureDeletion_Chain) {
- bool a_was_deleted = false;
- bool b_was_deleted = false;
- bool c_was_deleted = false;
- {
- MessageLoop loop(GetMessageLoopType());
- // The scoped_refptr for each of the below is held either by the chained
- // RecordDeletionProbe, or the bound RecordDeletionProbe::Run() callback.
- RecordDeletionProbe* a = new RecordDeletionProbe(nullptr, &a_was_deleted);
- RecordDeletionProbe* b = new RecordDeletionProbe(a, &b_was_deleted);
- RecordDeletionProbe* c = new RecordDeletionProbe(b, &c_was_deleted);
- loop.task_runner()->PostTask(FROM_HERE,
- BindOnce(&RecordDeletionProbe::Run, c));
- }
- EXPECT_TRUE(a_was_deleted);
- EXPECT_TRUE(b_was_deleted);
- EXPECT_TRUE(c_was_deleted);
-}
-
-namespace {
-
-void NestingFunc(int* depth) {
- if (*depth > 0) {
- *depth -= 1;
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&NestingFunc, depth));
-
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- RunLoop().Run();
- }
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-} // namespace
-
-TEST_P(MessageLoopTypedTest, Nesting) {
- MessageLoop loop(GetMessageLoopType());
-
- int depth = 50;
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&NestingFunc, &depth));
- RunLoop().Run();
- EXPECT_EQ(depth, 0);
-}
-
-TEST_P(MessageLoopTypedTest, RecursiveDenial1) {
- MessageLoop loop(GetMessageLoopType());
-
- EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- TaskList order;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, false));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2, false));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&QuitFunc, &order, 3));
-
- RunLoop().Run();
-
- // FIFO order.
- ASSERT_EQ(14U, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
- EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
- EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
- EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
- EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
-}
-
-namespace {
-
-void RecursiveSlowFunc(TaskList* order,
- int cookie,
- int depth,
- bool is_reentrant) {
- RecursiveFunc(order, cookie, depth, is_reentrant);
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
-}
-
-void OrderedFunc(TaskList* order, int cookie) {
- order->RecordStart(ORDERED, cookie);
- order->RecordEnd(ORDERED, cookie);
-}
-
-} // namespace
-
-TEST_P(MessageLoopTypedTest, RecursiveDenial3) {
- MessageLoop loop(GetMessageLoopType());
-
- EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- TaskList order;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecursiveSlowFunc, &order, 1, 2, false));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecursiveSlowFunc, &order, 2, 2, false));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&OrderedFunc, &order, 3),
- TimeDelta::FromMilliseconds(5));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&QuitFunc, &order, 4),
- TimeDelta::FromMilliseconds(5));
-
- RunLoop().Run();
-
- // FIFO order.
- ASSERT_EQ(16U, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
- EXPECT_EQ(order.Get(4), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(5), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 3, true));
- EXPECT_EQ(order.Get(7), TaskItem(ORDERED, 3, false));
- EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
- EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 4, true));
- EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 4, false));
- EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(14), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(15), TaskItem(RECURSIVE, 2, false));
-}
-
-TEST_P(MessageLoopTypedTest, RecursiveSupport1) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecursiveFunc, &order, 1, 2, true));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RecursiveFunc, &order, 2, 2, true));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&QuitFunc, &order, 3));
-
- RunLoop().Run();
-
- // FIFO order.
- ASSERT_EQ(14U, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(2), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(3), TaskItem(RECURSIVE, 2, false));
- EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
- EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
- EXPECT_EQ(order.Get(6), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(7), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(8), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(9), TaskItem(RECURSIVE, 2, false));
- EXPECT_EQ(order.Get(10), TaskItem(RECURSIVE, 1, true));
- EXPECT_EQ(order.Get(11), TaskItem(RECURSIVE, 1, false));
- EXPECT_EQ(order.Get(12), TaskItem(RECURSIVE, 2, true));
- EXPECT_EQ(order.Get(13), TaskItem(RECURSIVE, 2, false));
-}
-
-// Tests that non nestable tasks run in FIFO if there are no nested loops.
-TEST_P(MessageLoopTypedTest, NonNestableWithNoNesting) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
- FROM_HERE, BindOnce(&OrderedFunc, &order, 1));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&QuitFunc, &order, 3));
- RunLoop().Run();
-
- // FIFO order.
- ASSERT_EQ(6U, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(ORDERED, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 1, false));
- EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(3), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(order.Get(4), TaskItem(QUITMESSAGELOOP, 3, true));
- EXPECT_EQ(order.Get(5), TaskItem(QUITMESSAGELOOP, 3, false));
-}
-
-namespace {
-
-void FuncThatPumps(TaskList* order, int cookie) {
- order->RecordStart(PUMPS, cookie);
- RunLoop(RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
- order->RecordEnd(PUMPS, cookie);
-}
-
-void SleepFunc(TaskList* order, int cookie, TimeDelta delay) {
- order->RecordStart(SLEEP, cookie);
- PlatformThread::Sleep(delay);
- order->RecordEnd(SLEEP, cookie);
-}
-
-} // namespace
-
-// Tests that non nestable tasks don't run when there's code in the call stack.
-TEST_P(MessageLoopTypedTest, NonNestableDelayedInNestedLoop) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&FuncThatPumps, &order, 1));
- ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
- FROM_HERE, BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 3));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&SleepFunc, &order, 4, TimeDelta::FromMilliseconds(50)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 5));
- ThreadTaskRunnerHandle::Get()->PostNonNestableTask(
- FROM_HERE, BindOnce(&QuitFunc, &order, 6));
-
- RunLoop().Run();
-
- // FIFO order.
- ASSERT_EQ(12U, order.Size());
- EXPECT_EQ(order.Get(0), TaskItem(PUMPS, 1, true));
- EXPECT_EQ(order.Get(1), TaskItem(ORDERED, 3, true));
- EXPECT_EQ(order.Get(2), TaskItem(ORDERED, 3, false));
- EXPECT_EQ(order.Get(3), TaskItem(SLEEP, 4, true));
- EXPECT_EQ(order.Get(4), TaskItem(SLEEP, 4, false));
- EXPECT_EQ(order.Get(5), TaskItem(ORDERED, 5, true));
- EXPECT_EQ(order.Get(6), TaskItem(ORDERED, 5, false));
- EXPECT_EQ(order.Get(7), TaskItem(PUMPS, 1, false));
- EXPECT_EQ(order.Get(8), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(9), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(order.Get(10), TaskItem(QUITMESSAGELOOP, 6, true));
- EXPECT_EQ(order.Get(11), TaskItem(QUITMESSAGELOOP, 6, false));
-}
-
-namespace {
-
-void FuncThatRuns(TaskList* order, int cookie, RunLoop* run_loop) {
- order->RecordStart(RUNS, cookie);
- {
- MessageLoopCurrent::ScopedNestableTaskAllower allow;
- run_loop->Run();
- }
- order->RecordEnd(RUNS, cookie);
-}
-
-void FuncThatQuitsNow() {
- base::RunLoop::QuitCurrentDeprecated();
-}
-
-} // namespace
-
-// Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
-TEST_P(MessageLoopTypedTest, QuitNow) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&FuncThatQuitsNow));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 3));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&FuncThatQuitsNow));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&OrderedFunc, &order, 4)); // never runs
-
- RunLoop().Run();
-
- ASSERT_EQ(6U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
-TEST_P(MessageLoopTypedTest, RunLoopQuitTop) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop outer_run_loop;
- RunLoop nested_run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- outer_run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_run_loop.QuitClosure());
-
- outer_run_loop.Run();
-
- ASSERT_EQ(4U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
-TEST_P(MessageLoopTypedTest, RunLoopQuitNested) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop outer_run_loop;
- RunLoop nested_run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- outer_run_loop.QuitClosure());
-
- outer_run_loop.Run();
-
- ASSERT_EQ(4U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Quits current loop and immediately runs a nested loop.
-void QuitAndRunNestedLoop(TaskList* order,
- int cookie,
- RunLoop* outer_run_loop,
- RunLoop* nested_run_loop) {
- order->RecordStart(RUNS, cookie);
- outer_run_loop->Quit();
- nested_run_loop->Run();
- order->RecordEnd(RUNS, cookie);
-}
-
-// Test that we can run nested loop after quitting the current one.
-TEST_P(MessageLoopTypedTest, RunLoopNestedAfterQuit) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop outer_run_loop;
- RunLoop nested_run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&QuitAndRunNestedLoop, &order, 1, &outer_run_loop,
- &nested_run_loop));
-
- outer_run_loop.Run();
-
- ASSERT_EQ(2U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
-TEST_P(MessageLoopTypedTest, RunLoopQuitBogus) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop outer_run_loop;
- RunLoop nested_run_loop;
- RunLoop bogus_run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_run_loop)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- bogus_run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- outer_run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_run_loop.QuitClosure());
-
- outer_run_loop.Run();
-
- ASSERT_EQ(4U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Tests RunLoopQuit only quits the corresponding MessageLoop::Run.
-TEST_P(MessageLoopTypedTest, RunLoopQuitDeep) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop outer_run_loop;
- RunLoop nested_loop1;
- RunLoop nested_loop2;
- RunLoop nested_loop3;
- RunLoop nested_loop4;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&nested_loop1)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatRuns, &order, 2, Unretained(&nested_loop2)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatRuns, &order, 3, Unretained(&nested_loop3)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatRuns, &order, 4, Unretained(&nested_loop4)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 5));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- outer_run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 6));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_loop1.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 7));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_loop2.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 8));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_loop3.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 9));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- nested_loop4.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 10));
-
- outer_run_loop.Run();
-
- ASSERT_EQ(18U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 5, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 6, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 7, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 8, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 9, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 4, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 3, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 2, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Tests RunLoopQuit works before RunWithID.
-TEST_P(MessageLoopTypedTest, RunLoopQuitOrderBefore) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop run_loop;
-
- run_loop.Quit();
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&OrderedFunc, &order, 1)); // never runs
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatQuitsNow)); // never runs
-
- run_loop.Run();
-
- ASSERT_EQ(0U, order.Size());
-}
-
-// Tests RunLoopQuit works during RunWithID.
-TEST_P(MessageLoopTypedTest, RunLoopQuitOrderDuring) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 1));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&OrderedFunc, &order, 2)); // never runs
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatQuitsNow)); // never runs
-
- run_loop.Run();
-
- ASSERT_EQ(2U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 1, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// Tests RunLoopQuit works after RunWithID.
-TEST_P(MessageLoopTypedTest, RunLoopQuitOrderAfter) {
- MessageLoop loop(GetMessageLoopType());
-
- TaskList order;
-
- RunLoop run_loop;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&FuncThatRuns, &order, 1, Unretained(&run_loop)));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 2));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&FuncThatQuitsNow));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 3));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, run_loop.QuitClosure()); // has no affect
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&OrderedFunc, &order, 4));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&FuncThatQuitsNow));
-
- RunLoop outer_run_loop;
- outer_run_loop.Run();
-
- ASSERT_EQ(8U, order.Size());
- int task_index = 0;
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 2, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(RUNS, 1, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 3, false));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, true));
- EXPECT_EQ(order.Get(task_index++), TaskItem(ORDERED, 4, false));
- EXPECT_EQ(static_cast<size_t>(task_index), order.Size());
-}
-
-// There was a bug in the MessagePumpGLib where posting tasks recursively
-// caused the message loop to hang, due to the buffer of the internal pipe
-// becoming full. Test all MessageLoop types to ensure this issue does not
-// exist in other MessagePumps.
-//
-// On Linux, the pipe buffer size is 64KiB by default. The bug caused one
-// byte accumulated in the pipe per two posts, so we should repeat 128K
-// times to reproduce the bug.
-TEST_P(MessageLoopTypedTest, RecursivePosts) {
- const int kNumTimes = 1 << 17;
- MessageLoop loop(GetMessageLoopType());
- loop.task_runner()->PostTask(FROM_HERE,
- BindOnce(&PostNTasksThenQuit, kNumTimes));
- RunLoop().Run();
-}
-
-TEST_P(MessageLoopTypedTest, NestableTasksAllowedAtTopLevel) {
- MessageLoop loop(GetMessageLoopType());
- EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
-}
-
-// Nestable tasks shouldn't be allowed to run reentrantly by default (regression
-// test for https://crbug.com/754112).
-TEST_P(MessageLoopTypedTest, NestableTasksDisallowedByDefault) {
- MessageLoop loop(GetMessageLoopType());
- RunLoop run_loop;
- loop.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* run_loop) {
- EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- run_loop->Quit();
- },
- Unretained(&run_loop)));
- run_loop.Run();
-}
-
-TEST_P(MessageLoopTypedTest, NestableTasksProcessedWhenRunLoopAllows) {
- MessageLoop loop(GetMessageLoopType());
- RunLoop run_loop;
- loop.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* run_loop) {
- // This test would hang if this RunLoop wasn't of type
- // kNestableTasksAllowed (i.e. this is testing that this is
- // processed and doesn't hang).
- RunLoop nested_run_loop(RunLoop::Type::kNestableTasksAllowed);
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* nested_run_loop) {
- // Each additional layer of application task nesting
- // requires its own allowance. The kNestableTasksAllowed
- // RunLoop allowed this task to be processed but further
- // nestable tasks are by default disallowed from this
- // layer.
- EXPECT_FALSE(
- MessageLoopCurrent::Get()->NestableTasksAllowed());
- nested_run_loop->Quit();
- },
- Unretained(&nested_run_loop)));
- nested_run_loop.Run();
-
- run_loop->Quit();
- },
- Unretained(&run_loop)));
- run_loop.Run();
-}
-
-TEST_P(MessageLoopTypedTest, NestableTasksAllowedExplicitlyInScope) {
- MessageLoop loop(GetMessageLoopType());
- RunLoop run_loop;
- loop.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* run_loop) {
- {
- MessageLoopCurrent::ScopedNestableTaskAllower
- allow_nestable_tasks;
- EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- }
- EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- run_loop->Quit();
- },
- Unretained(&run_loop)));
- run_loop.Run();
-}
-
-TEST_P(MessageLoopTypedTest, NestableTasksAllowedManually) {
- MessageLoop loop(GetMessageLoopType());
- RunLoop run_loop;
- loop.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* run_loop) {
- EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- EXPECT_TRUE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(false);
- EXPECT_FALSE(MessageLoopCurrent::Get()->NestableTasksAllowed());
- run_loop->Quit();
- },
- Unretained(&run_loop)));
- run_loop.Run();
-}
-
-INSTANTIATE_TEST_CASE_P(
- ,
- MessageLoopTypedTest,
- ::testing::Values(MessageLoopTypedTestParams(
- MessageLoop::TYPE_DEFAULT,
- TaskSchedulerAvailability::NO_TASK_SCHEDULER),
- MessageLoopTypedTestParams(
- MessageLoop::TYPE_IO,
- TaskSchedulerAvailability::NO_TASK_SCHEDULER),
- MessageLoopTypedTestParams(
- MessageLoop::TYPE_UI,
- TaskSchedulerAvailability::NO_TASK_SCHEDULER),
- MessageLoopTypedTestParams(
- MessageLoop::TYPE_DEFAULT,
- TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
- MessageLoopTypedTestParams(
- MessageLoop::TYPE_IO,
- TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
- MessageLoopTypedTestParams(
- MessageLoop::TYPE_UI,
- TaskSchedulerAvailability::WITH_TASK_SCHEDULER)),
- MessageLoopTypedTest::ParamInfoToString);
-
-#if defined(OS_WIN)
-// Verifies that the MessageLoop ignores WM_QUIT, rather than quitting.
-// Users of MessageLoop typically expect to control when their RunLoops stop
-// Run()ning explicitly, via QuitClosure() etc (see https://crbug.com/720078)
-TEST_P(MessageLoopTest, WmQuitIsIgnored) {
- MessageLoop loop(MessageLoop::TYPE_UI);
- RunLoop run_loop;
- // Post a WM_QUIT message to the current thread.
- ::PostQuitMessage(0);
-
- // Post a task to the current thread, with a small delay to make it less
- // likely that we process the posted task before looking for WM_* messages.
- bool task_was_run = false;
- loop.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(
- [](bool* flag, OnceClosure closure) {
- *flag = true;
- std::move(closure).Run();
- },
- &task_was_run, run_loop.QuitClosure()),
- TestTimeouts::tiny_timeout());
-
- // Run the loop, and ensure that the posted task is processed before we quit.
- run_loop.Run();
- EXPECT_TRUE(task_was_run);
-}
-
-TEST_P(MessageLoopTest, PostDelayedTask_SharedTimer_SubPump) {
- RunTest_PostDelayedTask_SharedTimer_SubPump();
-}
-
-// This test occasionally hangs. See http://crbug.com/44567.
-TEST_P(MessageLoopTest, DISABLED_RecursiveDenial2) {
- RunTest_RecursiveDenial2(MessageLoop::TYPE_DEFAULT);
- RunTest_RecursiveDenial2(MessageLoop::TYPE_UI);
- RunTest_RecursiveDenial2(MessageLoop::TYPE_IO);
-}
-
-TEST_P(MessageLoopTest, RecursiveSupport2) {
- // This test requires a UI loop.
- RunTest_RecursiveSupport2(MessageLoop::TYPE_UI);
-}
-#endif // defined(OS_WIN)
-
-TEST_P(MessageLoopTest, TaskObserver) {
- const int kNumPosts = 6;
- DummyTaskObserver observer(kNumPosts);
-
- MessageLoop loop;
- loop.AddTaskObserver(&observer);
- loop.task_runner()->PostTask(FROM_HERE,
- BindOnce(&PostNTasksThenQuit, kNumPosts));
- RunLoop().Run();
- loop.RemoveTaskObserver(&observer);
-
- EXPECT_EQ(kNumPosts, observer.num_tasks_started());
- EXPECT_EQ(kNumPosts, observer.num_tasks_processed());
-}
-
-#if defined(OS_WIN)
-TEST_P(MessageLoopTest, IOHandler) {
- RunTest_IOHandler();
-}
-
-TEST_P(MessageLoopTest, WaitForIO) {
- RunTest_WaitForIO();
-}
-
-TEST_P(MessageLoopTest, HighResolutionTimer) {
- MessageLoop message_loop;
- Time::EnableHighResolutionTimer(true);
-
- constexpr TimeDelta kFastTimer = TimeDelta::FromMilliseconds(5);
- constexpr TimeDelta kSlowTimer = TimeDelta::FromMilliseconds(100);
-
- {
- // Post a fast task to enable the high resolution timers.
- RunLoop run_loop;
- message_loop.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* run_loop) {
- EXPECT_TRUE(Time::IsHighResolutionTimerInUse());
- run_loop->QuitWhenIdle();
- },
- &run_loop),
- kFastTimer);
- run_loop.Run();
- }
- EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
- {
- // Check that a slow task does not trigger the high resolution logic.
- RunLoop run_loop;
- message_loop.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(
- [](RunLoop* run_loop) {
- EXPECT_FALSE(Time::IsHighResolutionTimerInUse());
- run_loop->QuitWhenIdle();
- },
- &run_loop),
- kSlowTimer);
- run_loop.Run();
- }
- Time::EnableHighResolutionTimer(false);
- Time::ResetHighResolutionTimerUsage();
-}
-
-#endif // defined(OS_WIN)
-
-namespace {
-// Inject a test point for recording the destructor calls for Closure objects
-// send to MessageLoop::PostTask(). It is awkward usage since we are trying to
-// hook the actual destruction, which is not a common operation.
-class DestructionObserverProbe :
- public RefCounted<DestructionObserverProbe> {
- public:
- DestructionObserverProbe(bool* task_destroyed,
- bool* destruction_observer_called)
- : task_destroyed_(task_destroyed),
- destruction_observer_called_(destruction_observer_called) {
- }
- virtual void Run() {
- // This task should never run.
- ADD_FAILURE();
- }
- private:
- friend class RefCounted<DestructionObserverProbe>;
-
- virtual ~DestructionObserverProbe() {
- EXPECT_FALSE(*destruction_observer_called_);
- *task_destroyed_ = true;
- }
-
- bool* task_destroyed_;
- bool* destruction_observer_called_;
-};
-
-class MLDestructionObserver : public MessageLoopCurrent::DestructionObserver {
- public:
- MLDestructionObserver(bool* task_destroyed, bool* destruction_observer_called)
- : task_destroyed_(task_destroyed),
- destruction_observer_called_(destruction_observer_called),
- task_destroyed_before_message_loop_(false) {
- }
- void WillDestroyCurrentMessageLoop() override {
- task_destroyed_before_message_loop_ = *task_destroyed_;
- *destruction_observer_called_ = true;
- }
- bool task_destroyed_before_message_loop() const {
- return task_destroyed_before_message_loop_;
- }
- private:
- bool* task_destroyed_;
- bool* destruction_observer_called_;
- bool task_destroyed_before_message_loop_;
-};
-
-} // namespace
-
-TEST_P(MessageLoopTest, DestructionObserverTest) {
- // Verify that the destruction observer gets called at the very end (after
- // all the pending tasks have been destroyed).
- MessageLoop* loop = new MessageLoop;
- const TimeDelta kDelay = TimeDelta::FromMilliseconds(100);
-
- bool task_destroyed = false;
- bool destruction_observer_called = false;
-
- MLDestructionObserver observer(&task_destroyed, &destruction_observer_called);
- loop->AddDestructionObserver(&observer);
- loop->task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&DestructionObserverProbe::Run,
- new DestructionObserverProbe(&task_destroyed,
- &destruction_observer_called)),
- kDelay);
- delete loop;
- EXPECT_TRUE(observer.task_destroyed_before_message_loop());
- // The task should have been destroyed when we deleted the loop.
- EXPECT_TRUE(task_destroyed);
- EXPECT_TRUE(destruction_observer_called);
-}
-
-
-// Verify that MessageLoop sets ThreadMainTaskRunner::current() and it
-// posts tasks on that message loop.
-TEST_P(MessageLoopTest, ThreadMainTaskRunner) {
- MessageLoop loop;
-
- scoped_refptr<Foo> foo(new Foo());
- std::string a("a");
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, a));
-
- // Post quit task;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&RunLoop::QuitCurrentWhenIdleDeprecated));
-
- // Now kick things off
- RunLoop().Run();
-
- EXPECT_EQ(foo->test_count(), 1);
- EXPECT_EQ(foo->result(), "a");
-}
-
-TEST_P(MessageLoopTest, IsType) {
- MessageLoop loop(MessageLoop::TYPE_UI);
- EXPECT_TRUE(loop.IsType(MessageLoop::TYPE_UI));
- EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_IO));
- EXPECT_FALSE(loop.IsType(MessageLoop::TYPE_DEFAULT));
-}
-
-#if defined(OS_WIN)
-void EmptyFunction() {}
-
-void PostMultipleTasks() {
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(&EmptyFunction));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(&EmptyFunction));
-}
-
-static const int kSignalMsg = WM_USER + 2;
-
-void PostWindowsMessage(HWND message_hwnd) {
- PostMessage(message_hwnd, kSignalMsg, 0, 2);
-}
-
-void EndTest(bool* did_run, HWND hwnd) {
- *did_run = true;
- PostMessage(hwnd, WM_CLOSE, 0, 0);
-}
-
-int kMyMessageFilterCode = 0x5002;
-
-LRESULT CALLBACK TestWndProcThunk(HWND hwnd, UINT message,
- WPARAM wparam, LPARAM lparam) {
- if (message == WM_CLOSE)
- EXPECT_TRUE(DestroyWindow(hwnd));
- if (message != kSignalMsg)
- return DefWindowProc(hwnd, message, wparam, lparam);
-
- switch (lparam) {
- case 1:
- // First, we post a task that will post multiple no-op tasks to make sure
- // that the pump's incoming task queue does not become empty during the
- // test.
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- base::BindOnce(&PostMultipleTasks));
- // Next, we post a task that posts a windows message to trigger the second
- // stage of the test.
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&PostWindowsMessage, hwnd));
- break;
- case 2:
- // Since we're about to enter a modal loop, tell the message loop that we
- // intend to nest tasks.
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- bool did_run = false;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&EndTest, &did_run, hwnd));
- // Run a nested windows-style message loop and verify that our task runs. If
- // it doesn't, then we'll loop here until the test times out.
- MSG msg;
- while (GetMessage(&msg, 0, 0, 0)) {
- if (!CallMsgFilter(&msg, kMyMessageFilterCode))
- DispatchMessage(&msg);
- // If this message is a WM_CLOSE, explicitly exit the modal loop. Posting
- // a WM_QUIT should handle this, but unfortunately MessagePumpWin eats
- // WM_QUIT messages even when running inside a modal loop.
- if (msg.message == WM_CLOSE)
- break;
- }
- EXPECT_TRUE(did_run);
- RunLoop::QuitCurrentWhenIdleDeprecated();
- break;
- }
- return 0;
-}
-
-TEST_P(MessageLoopTest, AlwaysHaveUserMessageWhenNesting) {
- MessageLoop loop(MessageLoop::TYPE_UI);
- HINSTANCE instance = CURRENT_MODULE();
- WNDCLASSEX wc = {0};
- wc.cbSize = sizeof(wc);
- wc.lpfnWndProc = TestWndProcThunk;
- wc.hInstance = instance;
- wc.lpszClassName = L"MessageLoopTest_HWND";
- ATOM atom = RegisterClassEx(&wc);
- ASSERT_TRUE(atom);
-
- HWND message_hwnd = CreateWindow(MAKEINTATOM(atom), 0, 0, 0, 0, 0, 0,
- HWND_MESSAGE, 0, instance, 0);
- ASSERT_TRUE(message_hwnd) << GetLastError();
-
- ASSERT_TRUE(PostMessage(message_hwnd, kSignalMsg, 0, 1));
-
- RunLoop().Run();
-
- ASSERT_TRUE(UnregisterClass(MAKEINTATOM(atom), instance));
-}
-#endif // defined(OS_WIN)
-
-TEST_P(MessageLoopTest, SetTaskRunner) {
- MessageLoop loop;
- scoped_refptr<SingleThreadTaskRunner> new_runner(new TestSimpleTaskRunner());
-
- loop.SetTaskRunner(new_runner);
- EXPECT_EQ(new_runner, loop.task_runner());
- EXPECT_EQ(new_runner, ThreadTaskRunnerHandle::Get());
-}
-
-TEST_P(MessageLoopTest, OriginalRunnerWorks) {
- MessageLoop loop;
- scoped_refptr<SingleThreadTaskRunner> new_runner(new TestSimpleTaskRunner());
- scoped_refptr<SingleThreadTaskRunner> original_runner(loop.task_runner());
- loop.SetTaskRunner(new_runner);
-
- scoped_refptr<Foo> foo(new Foo());
- original_runner->PostTask(FROM_HERE, BindOnce(&Foo::Test1ConstRef, foo, "a"));
- RunLoop().RunUntilIdle();
- EXPECT_EQ(1, foo->test_count());
-}
-
-TEST_P(MessageLoopTest, DeleteUnboundLoop) {
- // It should be possible to delete an unbound message loop on a thread which
- // already has another active loop. This happens when thread creation fails.
- MessageLoop loop;
- std::unique_ptr<MessageLoop> unbound_loop(MessageLoop::CreateUnbound(
- MessageLoop::TYPE_DEFAULT, MessageLoop::MessagePumpFactoryCallback()));
- unbound_loop.reset();
- EXPECT_EQ(&loop, MessageLoop::current());
- EXPECT_EQ(loop.task_runner(), ThreadTaskRunnerHandle::Get());
-}
-
-TEST_P(MessageLoopTest, ThreadName) {
- {
- std::string kThreadName("foo");
- MessageLoop loop;
- PlatformThread::SetName(kThreadName);
- EXPECT_EQ(kThreadName, loop.GetThreadName());
- }
-
- {
- std::string kThreadName("bar");
- base::Thread thread(kThreadName);
- ASSERT_TRUE(thread.StartAndWaitForTesting());
- EXPECT_EQ(kThreadName, thread.message_loop()->GetThreadName());
- }
-}
-
-// Verify that tasks posted to and code running in the scope of the same
-// MessageLoop access the same SequenceLocalStorage values.
-TEST_P(MessageLoopTest, SequenceLocalStorageSetGet) {
- MessageLoop loop;
-
- SequenceLocalStorageSlot<int> slot;
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&SequenceLocalStorageSlot<int>::Set, Unretained(&slot), 11));
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(
- [](SequenceLocalStorageSlot<int>* slot) {
- EXPECT_EQ(slot->Get(), 11);
- },
- &slot));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(slot.Get(), 11);
-}
-
-// Verify that tasks posted to and code running in different MessageLoops access
-// different SequenceLocalStorage values.
-TEST_P(MessageLoopTest, SequenceLocalStorageDifferentMessageLoops) {
- SequenceLocalStorageSlot<int> slot;
-
- {
- MessageLoop loop;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- BindOnce(&SequenceLocalStorageSlot<int>::Set, Unretained(&slot), 11));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(slot.Get(), 11);
- }
-
- MessageLoop loop;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(
- [](SequenceLocalStorageSlot<int>* slot) {
- EXPECT_NE(slot->Get(), 11);
- },
- &slot));
-
- RunLoop().RunUntilIdle();
- EXPECT_NE(slot.Get(), 11);
-}
-
-INSTANTIATE_TEST_CASE_P(
- ,
- MessageLoopTest,
- ::testing::Values(TaskSchedulerAvailability::NO_TASK_SCHEDULER,
- TaskSchedulerAvailability::WITH_TASK_SCHEDULER),
- MessageLoopTest::ParamInfoToString);
-
-} // namespace base
diff --git a/base/message_loop/message_pump_glib_unittest.cc b/base/message_loop/message_pump_glib_unittest.cc
deleted file mode 100644
index 70be2a4..0000000
--- a/base/message_loop/message_pump_glib_unittest.cc
+++ /dev/null
@@ -1,523 +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_glib.h"
-
-#include <glib.h>
-#include <math.h>
-
-#include <algorithm>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-// This class injects dummy "events" into the GLib loop. When "handled" these
-// events can run tasks. This is intended to mock gtk events (the corresponding
-// GLib source runs at the same priority).
-class EventInjector {
- public:
- EventInjector() : processed_events_(0) {
- source_ = static_cast<Source*>(g_source_new(&SourceFuncs, sizeof(Source)));
- source_->injector = this;
- g_source_attach(source_, nullptr);
- g_source_set_can_recurse(source_, TRUE);
- }
-
- ~EventInjector() {
- g_source_destroy(source_);
- g_source_unref(source_);
- }
-
- int HandlePrepare() {
- // If the queue is empty, block.
- if (events_.empty())
- return -1;
- TimeDelta delta = events_[0].time - Time::NowFromSystemTime();
- return std::max(0, static_cast<int>(ceil(delta.InMillisecondsF())));
- }
-
- bool HandleCheck() {
- if (events_.empty())
- return false;
- return events_[0].time <= Time::NowFromSystemTime();
- }
-
- void HandleDispatch() {
- if (events_.empty())
- return;
- Event event = std::move(events_[0]);
- events_.erase(events_.begin());
- ++processed_events_;
- if (!event.callback.is_null())
- std::move(event.callback).Run();
- else if (!event.task.is_null())
- std::move(event.task).Run();
- }
-
- // Adds an event to the queue. When "handled", executes |callback|.
- // delay_ms is relative to the last event if any, or to Now() otherwise.
- void AddEvent(int delay_ms, OnceClosure callback) {
- AddEventHelper(delay_ms, std::move(callback), OnceClosure());
- }
-
- void AddDummyEvent(int delay_ms) {
- AddEventHelper(delay_ms, OnceClosure(), OnceClosure());
- }
-
- void AddEventAsTask(int delay_ms, OnceClosure task) {
- AddEventHelper(delay_ms, OnceClosure(), std::move(task));
- }
-
- void Reset() {
- processed_events_ = 0;
- events_.clear();
- }
-
- int processed_events() const { return processed_events_; }
-
- private:
- struct Event {
- Time time;
- OnceClosure callback;
- OnceClosure task;
- };
-
- struct Source : public GSource {
- EventInjector* injector;
- };
-
- void AddEventHelper(int delay_ms, OnceClosure callback, OnceClosure task) {
- Time last_time;
- if (!events_.empty())
- last_time = (events_.end()-1)->time;
- else
- last_time = Time::NowFromSystemTime();
-
- Time future = last_time + TimeDelta::FromMilliseconds(delay_ms);
- EventInjector::Event event = {future, std::move(callback), std::move(task)};
- events_.push_back(std::move(event));
- }
-
- static gboolean Prepare(GSource* source, gint* timeout_ms) {
- *timeout_ms = static_cast<Source*>(source)->injector->HandlePrepare();
- return FALSE;
- }
-
- static gboolean Check(GSource* source) {
- return static_cast<Source*>(source)->injector->HandleCheck();
- }
-
- static gboolean Dispatch(GSource* source,
- GSourceFunc unused_func,
- gpointer unused_data) {
- static_cast<Source*>(source)->injector->HandleDispatch();
- return TRUE;
- }
-
- Source* source_;
- std::vector<Event> events_;
- int processed_events_;
- static GSourceFuncs SourceFuncs;
- DISALLOW_COPY_AND_ASSIGN(EventInjector);
-};
-
-GSourceFuncs EventInjector::SourceFuncs = {EventInjector::Prepare,
- EventInjector::Check,
- EventInjector::Dispatch, nullptr};
-
-void IncrementInt(int *value) {
- ++*value;
-}
-
-// Checks how many events have been processed by the injector.
-void ExpectProcessedEvents(EventInjector* injector, int count) {
- EXPECT_EQ(injector->processed_events(), count);
-}
-
-// Posts a task on the current message loop.
-void PostMessageLoopTask(const Location& from_here, OnceClosure task) {
- ThreadTaskRunnerHandle::Get()->PostTask(from_here, std::move(task));
-}
-
-// Test fixture.
-class MessagePumpGLibTest : public testing::Test {
- public:
- MessagePumpGLibTest() : loop_(nullptr), injector_(nullptr) {}
-
- // Overridden from testing::Test:
- void SetUp() override {
- loop_ = new MessageLoop(MessageLoop::TYPE_UI);
- injector_ = new EventInjector();
- }
- void TearDown() override {
- delete injector_;
- injector_ = nullptr;
- delete loop_;
- loop_ = nullptr;
- }
-
- MessageLoop* loop() const { return loop_; }
- EventInjector* injector() const { return injector_; }
-
- private:
- MessageLoop* loop_;
- EventInjector* injector_;
- DISALLOW_COPY_AND_ASSIGN(MessagePumpGLibTest);
-};
-
-} // namespace
-
-TEST_F(MessagePumpGLibTest, TestQuit) {
- // Checks that Quit works and that the basic infrastructure is working.
-
- // Quit from a task
- RunLoop().RunUntilIdle();
- EXPECT_EQ(0, injector()->processed_events());
-
- injector()->Reset();
- // Quit from an event
- injector()->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- RunLoop().Run();
- EXPECT_EQ(1, injector()->processed_events());
-}
-
-TEST_F(MessagePumpGLibTest, TestEventTaskInterleave) {
- // Checks that tasks posted by events are executed before the next event if
- // the posted task queue is empty.
- // MessageLoop doesn't make strong guarantees that it is the case, but the
- // current implementation ensures it and the tests below rely on it.
- // If changes cause this test to fail, it is reasonable to change it, but
- // TestWorkWhileWaitingForEvents and TestEventsWhileWaitingForWork have to be
- // changed accordingly, otherwise they can become flaky.
- injector()->AddEventAsTask(0, DoNothing());
- OnceClosure check_task =
- BindOnce(&ExpectProcessedEvents, Unretained(injector()), 2);
- OnceClosure posted_task =
- BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task));
- injector()->AddEventAsTask(0, std::move(posted_task));
- injector()->AddEventAsTask(0, DoNothing());
- injector()->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- RunLoop().Run();
- EXPECT_EQ(4, injector()->processed_events());
-
- injector()->Reset();
- injector()->AddEventAsTask(0, DoNothing());
- check_task = BindOnce(&ExpectProcessedEvents, Unretained(injector()), 2);
- posted_task =
- BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task));
- injector()->AddEventAsTask(0, std::move(posted_task));
- injector()->AddEventAsTask(10, DoNothing());
- injector()->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- RunLoop().Run();
- EXPECT_EQ(4, injector()->processed_events());
-}
-
-TEST_F(MessagePumpGLibTest, TestWorkWhileWaitingForEvents) {
- int task_count = 0;
- // Tests that we process tasks while waiting for new events.
- // The event queue is empty at first.
- for (int i = 0; i < 10; ++i) {
- loop()->task_runner()->PostTask(FROM_HERE,
- BindOnce(&IncrementInt, &task_count));
- }
- // After all the previous tasks have executed, enqueue an event that will
- // quit.
- loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&EventInjector::AddEvent, Unretained(injector()), 0,
- RunLoop::QuitCurrentWhenIdleClosureDeprecated()));
- RunLoop().Run();
- ASSERT_EQ(10, task_count);
- EXPECT_EQ(1, injector()->processed_events());
-
- // Tests that we process delayed tasks while waiting for new events.
- injector()->Reset();
- task_count = 0;
- for (int i = 0; i < 10; ++i) {
- loop()->task_runner()->PostDelayedTask(FROM_HERE,
- BindOnce(&IncrementInt, &task_count),
- TimeDelta::FromMilliseconds(10 * i));
- }
- // After all the previous tasks have executed, enqueue an event that will
- // quit.
- // This relies on the fact that delayed tasks are executed in delay order.
- // That is verified in message_loop_unittest.cc.
- loop()->task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(&EventInjector::AddEvent, Unretained(injector()), 10,
- RunLoop::QuitCurrentWhenIdleClosureDeprecated()),
- TimeDelta::FromMilliseconds(150));
- RunLoop().Run();
- ASSERT_EQ(10, task_count);
- EXPECT_EQ(1, injector()->processed_events());
-}
-
-TEST_F(MessagePumpGLibTest, TestEventsWhileWaitingForWork) {
- // Tests that we process events while waiting for work.
- // The event queue is empty at first.
- for (int i = 0; i < 10; ++i) {
- injector()->AddDummyEvent(0);
- }
- // After all the events have been processed, post a task that will check that
- // the events have been processed (note: the task executes after the event
- // that posted it has been handled, so we expect 11 at that point).
- OnceClosure check_task =
- BindOnce(&ExpectProcessedEvents, Unretained(injector()), 11);
- OnceClosure posted_task =
- BindOnce(&PostMessageLoopTask, FROM_HERE, std::move(check_task));
- injector()->AddEventAsTask(10, std::move(posted_task));
-
- // And then quit (relies on the condition tested by TestEventTaskInterleave).
- injector()->AddEvent(10, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- RunLoop().Run();
-
- EXPECT_EQ(12, injector()->processed_events());
-}
-
-namespace {
-
-// This class is a helper for the concurrent events / posted tasks test below.
-// It will quit the main loop once enough tasks and events have been processed,
-// while making sure there is always work to do and events in the queue.
-class ConcurrentHelper : public RefCounted<ConcurrentHelper> {
- public:
- explicit ConcurrentHelper(EventInjector* injector)
- : injector_(injector),
- event_count_(kStartingEventCount),
- task_count_(kStartingTaskCount) {
- }
-
- void FromTask() {
- if (task_count_ > 0) {
- --task_count_;
- }
- if (task_count_ == 0 && event_count_ == 0) {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- } else {
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, this));
- }
- }
-
- void FromEvent() {
- if (event_count_ > 0) {
- --event_count_;
- }
- if (task_count_ == 0 && event_count_ == 0) {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- } else {
- injector_->AddEventAsTask(0,
- BindOnce(&ConcurrentHelper::FromEvent, this));
- }
- }
-
- int event_count() const { return event_count_; }
- int task_count() const { return task_count_; }
-
- private:
- friend class RefCounted<ConcurrentHelper>;
-
- ~ConcurrentHelper() {}
-
- static const int kStartingEventCount = 20;
- static const int kStartingTaskCount = 20;
-
- EventInjector* injector_;
- int event_count_;
- int task_count_;
-};
-
-} // namespace
-
-TEST_F(MessagePumpGLibTest, TestConcurrentEventPostedTask) {
- // Tests that posted tasks don't starve events, nor the opposite.
- // We use the helper class above. We keep both event and posted task queues
- // full, the helper verifies that both tasks and events get processed.
- // If that is not the case, either event_count_ or task_count_ will not get
- // to 0, and MessageLoop::QuitWhenIdle() will never be called.
- scoped_refptr<ConcurrentHelper> helper = new ConcurrentHelper(injector());
-
- // Add 2 events to the queue to make sure it is always full (when we remove
- // the event before processing it).
- injector()->AddEventAsTask(0, BindOnce(&ConcurrentHelper::FromEvent, helper));
- injector()->AddEventAsTask(0, BindOnce(&ConcurrentHelper::FromEvent, helper));
-
- // Similarly post 2 tasks.
- loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, helper));
- loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&ConcurrentHelper::FromTask, helper));
-
- RunLoop().Run();
- EXPECT_EQ(0, helper->event_count());
- EXPECT_EQ(0, helper->task_count());
-}
-
-namespace {
-
-void AddEventsAndDrainGLib(EventInjector* injector) {
- // Add a couple of dummy events
- injector->AddDummyEvent(0);
- injector->AddDummyEvent(0);
- // Then add an event that will quit the main loop.
- injector->AddEvent(0, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
-
- // Post a couple of dummy tasks
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, DoNothing());
-
- // Drain the events
- while (g_main_context_pending(nullptr)) {
- g_main_context_iteration(nullptr, FALSE);
- }
-}
-
-} // namespace
-
-TEST_F(MessagePumpGLibTest, TestDrainingGLib) {
- // Tests that draining events using GLib works.
- loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&AddEventsAndDrainGLib, Unretained(injector())));
- RunLoop().Run();
-
- EXPECT_EQ(3, injector()->processed_events());
-}
-
-namespace {
-
-// Helper class that lets us run the GLib message loop.
-class GLibLoopRunner : public RefCounted<GLibLoopRunner> {
- public:
- GLibLoopRunner() : quit_(false) { }
-
- void RunGLib() {
- while (!quit_) {
- g_main_context_iteration(nullptr, TRUE);
- }
- }
-
- void RunLoop() {
- while (!quit_) {
- g_main_context_iteration(nullptr, TRUE);
- }
- }
-
- void Quit() {
- quit_ = true;
- }
-
- void Reset() {
- quit_ = false;
- }
-
- private:
- friend class RefCounted<GLibLoopRunner>;
-
- ~GLibLoopRunner() {}
-
- bool quit_;
-};
-
-void TestGLibLoopInternal(EventInjector* injector) {
- // Allow tasks to be processed from 'native' event loops.
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
-
- int task_count = 0;
- // Add a couple of dummy events
- injector->AddDummyEvent(0);
- injector->AddDummyEvent(0);
- // Post a couple of dummy tasks
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&IncrementInt, &task_count));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&IncrementInt, &task_count));
- // Delayed events
- injector->AddDummyEvent(10);
- injector->AddDummyEvent(10);
- // Delayed work
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&IncrementInt, &task_count),
- TimeDelta::FromMilliseconds(30));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&GLibLoopRunner::Quit, runner),
- TimeDelta::FromMilliseconds(40));
-
- // Run a nested, straight GLib message loop.
- runner->RunGLib();
-
- ASSERT_EQ(3, task_count);
- EXPECT_EQ(4, injector->processed_events());
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-void TestGtkLoopInternal(EventInjector* injector) {
- // Allow tasks to be processed from 'native' event loops.
- MessageLoopCurrent::Get()->SetNestableTasksAllowed(true);
- scoped_refptr<GLibLoopRunner> runner = new GLibLoopRunner();
-
- int task_count = 0;
- // Add a couple of dummy events
- injector->AddDummyEvent(0);
- injector->AddDummyEvent(0);
- // Post a couple of dummy tasks
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&IncrementInt, &task_count));
- ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE,
- BindOnce(&IncrementInt, &task_count));
- // Delayed events
- injector->AddDummyEvent(10);
- injector->AddDummyEvent(10);
- // Delayed work
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&IncrementInt, &task_count),
- TimeDelta::FromMilliseconds(30));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, BindOnce(&GLibLoopRunner::Quit, runner),
- TimeDelta::FromMilliseconds(40));
-
- // Run a nested, straight Gtk message loop.
- runner->RunLoop();
-
- ASSERT_EQ(3, task_count);
- EXPECT_EQ(4, injector->processed_events());
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-} // namespace
-
-TEST_F(MessagePumpGLibTest, TestGLibLoop) {
- // Tests that events and posted tasks are correctly executed if the message
- // loop is not run by MessageLoop::Run() but by a straight GLib loop.
- // Note that in this case we don't make strong guarantees about niceness
- // between events and posted tasks.
- loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&TestGLibLoopInternal, Unretained(injector())));
- RunLoop().Run();
-}
-
-TEST_F(MessagePumpGLibTest, TestGtkLoop) {
- // Tests that events and posted tasks are correctly executed if the message
- // loop is not run by MessageLoop::Run() but by a straight Gtk loop.
- // Note that in this case we don't make strong guarantees about niceness
- // between events and posted tasks.
- loop()->task_runner()->PostTask(
- FROM_HERE, BindOnce(&TestGtkLoopInternal, Unretained(injector())));
- RunLoop().Run();
-}
-
-} // namespace base
diff --git a/base/message_loop/message_pump_io_ios_unittest.cc b/base/message_loop/message_pump_io_ios_unittest.cc
deleted file mode 100644
index 4d15d44..0000000
--- a/base/message_loop/message_pump_io_ios_unittest.cc
+++ /dev/null
@@ -1,153 +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.
-
-#include "base/message_loop/message_pump_io_ios.h"
-
-#include <unistd.h>
-
-#include "base/macros.h"
-#include "base/posix/eintr_wrapper.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class MessagePumpIOSForIOTest : public testing::Test {
- protected:
- MessagePumpIOSForIOTest() = default;
- ~MessagePumpIOSForIOTest() override = default;
-
- void SetUp() override {
- int ret = pipe(pipefds_);
- ASSERT_EQ(0, ret);
- ret = pipe(alternate_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 HandleFdIOEvent(MessagePumpForIO::FdWatchController* watcher) {
- MessagePumpIOSForIO::HandleFdIOEvent(watcher->fdref_.get(),
- kCFFileDescriptorReadCallBack | kCFFileDescriptorWriteCallBack,
- watcher);
- }
-
- int pipefds_[2];
- int alternate_pipefds_[2];
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MessagePumpIOSForIOTest);
-};
-
-namespace {
-
-// Concrete implementation of MessagePumpIOSForIO::FdWatcher that does
-// nothing useful.
-class StupidWatcher : public MessagePumpIOSForIO::FdWatcher {
- public:
- ~StupidWatcher() override {}
-
- // base:MessagePumpIOSForIO::FdWatcher interface
- void OnFileCanReadWithoutBlocking(int fd) override {}
- void OnFileCanWriteWithoutBlocking(int fd) override {}
-};
-
-class BaseWatcher : public MessagePumpIOSForIO::FdWatcher {
- public:
- BaseWatcher(MessagePumpIOSForIO::FdWatchController* controller)
- : controller_(controller) {
- DCHECK(controller_);
- }
- ~BaseWatcher() override {}
-
- // MessagePumpIOSForIO::FdWatcher interface
- void OnFileCanReadWithoutBlocking(int /* fd */) override { NOTREACHED(); }
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override { NOTREACHED(); }
-
- protected:
- MessagePumpIOSForIO::FdWatchController* controller_;
-};
-
-class DeleteWatcher : public BaseWatcher {
- public:
- explicit DeleteWatcher(MessagePumpIOSForIO::FdWatchController* controller)
- : BaseWatcher(controller) {}
-
- ~DeleteWatcher() override { DCHECK(!controller_); }
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override {
- DCHECK(controller_);
- delete controller_;
- controller_ = NULL;
- }
-};
-
-TEST_F(MessagePumpIOSForIOTest, DeleteWatcher) {
- std::unique_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO);
- MessagePumpIOSForIO::FdWatchController* watcher =
- new MessagePumpIOSForIO::FdWatchController(FROM_HERE);
- DeleteWatcher delegate(watcher);
- pump->WatchFileDescriptor(pipefds_[1],
- false, MessagePumpIOSForIO::WATCH_READ_WRITE, watcher, &delegate);
-
- // Spoof a callback.
- HandleFdIOEvent(watcher);
-}
-
-class StopWatcher : public BaseWatcher {
- public:
- StopWatcher(MessagePumpIOSForIO::FdWatchController* controller,
- MessagePumpIOSForIO* pump,
- int fd_to_start_watching = -1)
- : BaseWatcher(controller),
- pump_(pump),
- fd_to_start_watching_(fd_to_start_watching) {}
-
- ~StopWatcher() override {}
-
- void OnFileCanWriteWithoutBlocking(int /* fd */) override {
- controller_->StopWatchingFileDescriptor();
- if (fd_to_start_watching_ >= 0) {
- pump_->WatchFileDescriptor(fd_to_start_watching_,
- false, MessagePumpIOSForIO::WATCH_READ_WRITE, controller_, this);
- }
- }
-
- private:
- MessagePumpIOSForIO* pump_;
- int fd_to_start_watching_;
-};
-
-TEST_F(MessagePumpIOSForIOTest, StopWatcher) {
- std::unique_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO);
- MessagePumpIOSForIO::FdWatchController watcher(FROM_HERE);
- StopWatcher delegate(&watcher, pump.get());
- pump->WatchFileDescriptor(pipefds_[1],
- false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate);
-
- // Spoof a callback.
- HandleFdIOEvent(&watcher);
-}
-
-TEST_F(MessagePumpIOSForIOTest, StopWatcherAndWatchSomethingElse) {
- std::unique_ptr<MessagePumpIOSForIO> pump(new MessagePumpIOSForIO);
- MessagePumpIOSForIO::FdWatchController watcher(FROM_HERE);
- StopWatcher delegate(&watcher, pump.get(), alternate_pipefds_[1]);
- pump->WatchFileDescriptor(pipefds_[1],
- false, MessagePumpIOSForIO::WATCH_READ_WRITE, &watcher, &delegate);
-
- // Spoof a callback.
- HandleFdIOEvent(&watcher);
-}
-
-} // namespace
-
-} // namespace base
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 bb26c29..0000000
--- 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_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/metrics/bucket_ranges_unittest.cc b/base/metrics/bucket_ranges_unittest.cc
deleted file mode 100644
index 481054c..0000000
--- a/base/metrics/bucket_ranges_unittest.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 "base/metrics/bucket_ranges.h"
-
-#include <stdint.h>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-TEST(BucketRangesTest, NormalSetup) {
- BucketRanges ranges(5);
- ASSERT_EQ(5u, ranges.size());
- ASSERT_EQ(4u, ranges.bucket_count());
-
- for (int i = 0; i < 5; ++i) {
- EXPECT_EQ(0, ranges.range(i));
- }
- EXPECT_EQ(0u, ranges.checksum());
-
- ranges.set_range(3, 100);
- EXPECT_EQ(100, ranges.range(3));
-}
-
-TEST(BucketRangesTest, Equals) {
- // Compare empty ranges.
- BucketRanges ranges1(3);
- BucketRanges ranges2(3);
- BucketRanges ranges3(5);
-
- EXPECT_TRUE(ranges1.Equals(&ranges2));
- EXPECT_FALSE(ranges1.Equals(&ranges3));
- EXPECT_FALSE(ranges2.Equals(&ranges3));
-
- // Compare full filled ranges.
- ranges1.set_range(0, 0);
- ranges1.set_range(1, 1);
- ranges1.set_range(2, 2);
- ranges1.set_checksum(100);
- ranges2.set_range(0, 0);
- ranges2.set_range(1, 1);
- ranges2.set_range(2, 2);
- ranges2.set_checksum(100);
-
- EXPECT_TRUE(ranges1.Equals(&ranges2));
-
- // Checksum does not match.
- ranges1.set_checksum(99);
- EXPECT_FALSE(ranges1.Equals(&ranges2));
- ranges1.set_checksum(100);
-
- // Range does not match.
- ranges1.set_range(1, 3);
- EXPECT_FALSE(ranges1.Equals(&ranges2));
-}
-
-TEST(BucketRangesTest, Checksum) {
- BucketRanges ranges(3);
- ranges.set_range(0, 0);
- ranges.set_range(1, 1);
- ranges.set_range(2, 2);
-
- ranges.ResetChecksum();
- EXPECT_EQ(289217253u, ranges.checksum());
-
- ranges.set_range(2, 3);
- EXPECT_FALSE(ranges.HasValidChecksum());
-
- ranges.ResetChecksum();
- EXPECT_EQ(2843835776u, ranges.checksum());
- EXPECT_TRUE(ranges.HasValidChecksum());
-}
-
-// Table was generated similarly to sample code for CRC-32 given on:
-// http://www.w3.org/TR/PNG/#D-CRCAppendix.
-TEST(BucketRangesTest, Crc32TableTest) {
- for (int i = 0; i < 256; ++i) {
- uint32_t checksum = i;
- for (int j = 0; j < 8; ++j) {
- const uint32_t kReversedPolynomial = 0xedb88320L;
- if (checksum & 1)
- checksum = kReversedPolynomial ^ (checksum >> 1);
- else
- checksum >>= 1;
- }
- EXPECT_EQ(kCrcTable[i], checksum);
- }
-}
-
-} // namespace
-} // 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 d310c0d..0000000
--- 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, ¶ms));
- 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, ¶ms));
- 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, ¶ms));
- 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, ¶ms));
- 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/field_trial_params_unittest.nc b/base/metrics/field_trial_params_unittest.nc
deleted file mode 100644
index 4c6005e..0000000
--- a/base/metrics/field_trial_params_unittest.nc
+++ /dev/null
@@ -1,47 +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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/feature_list.h"
-#include "base/metrics/field_trial_params.h"
-
-constexpr base::Feature kFeature{"NoCompileFeature"};
-
-enum Param { FOO, BAR };
-
-#if defined(NCTEST_NO_PARAM_TYPE) // [r"too few template arguments"]
-
-constexpr base::FeatureParam<> kParam{
- &kFeature, "Param"};
-
-#elif defined(NCTEST_VOID_PARAM_TYPE) // [r"unsupported FeatureParam<> type"]
-
-constexpr base::FeatureParam<void> kParam{
- &kFeature, "Param"};
-
-#elif defined(NCTEST_INVALID_PARAM_TYPE) // [r"unsupported FeatureParam<> type"]
-
-constexpr base::FeatureParam<size_t> kParam{
- &kFeature, "Param", 1u};
-
-#elif defined(NCTEST_ENUM_NULL_OPTIONS) // [r"candidate template ignored: could not match"]
-
-constexpr base::FeatureParam<Param> kParam{
- &kFeature, "Param", FOO, nullptr};
-
-#elif defined(NCTEST_ENUM_EMPTY_OPTIONS) // [r"zero-length arrays are not permitted"]
-
-constexpr base::FeatureParam<Param>::Option kParamOptions[] = {};
-constexpr base::FeatureParam<Param> kParam{
- &kFeature, "Param", FOO, &kParamOptions};
-
-#else
-
-void suppress_unused_variable_warning() {
- (void)kFeature;
-}
-
-#endif
diff --git a/base/metrics/field_trial_unittest.cc b/base/metrics/field_trial_unittest.cc
deleted file mode 100644
index 4d55697..0000000
--- a/base/metrics/field_trial_unittest.cc
+++ /dev/null
@@ -1,1400 +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/metrics/field_trial.h"
-
-#include <stddef.h>
-
-#include "base/base_switches.h"
-#include "base/feature_list.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/metrics/field_trial_param_associator.h"
-#include "base/rand_util.h"
-#include "base/run_loop.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/gtest_util.h"
-#include "base/test/mock_entropy_provider.h"
-#include "base/test/scoped_feature_list.h"
-#include "base/test/test_shared_memory_util.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Default group name used by several tests.
-const char kDefaultGroupName[] = "DefaultGroup";
-
-// 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);
-}
-
-// FieldTrialList::Observer implementation for testing.
-class TestFieldTrialObserver : public FieldTrialList::Observer {
- public:
- enum Type {
- ASYNCHRONOUS,
- SYNCHRONOUS,
- };
-
- TestFieldTrialObserver(Type type) : type_(type) {
- if (type == SYNCHRONOUS)
- FieldTrialList::SetSynchronousObserver(this);
- else
- FieldTrialList::AddObserver(this);
- }
-
- ~TestFieldTrialObserver() override {
- if (type_ == SYNCHRONOUS)
- FieldTrialList::RemoveSynchronousObserver(this);
- else
- FieldTrialList::RemoveObserver(this);
- }
-
- void OnFieldTrialGroupFinalized(const std::string& trial,
- const std::string& group) override {
- trial_name_ = trial;
- group_name_ = group;
- }
-
- const std::string& trial_name() const { return trial_name_; }
- const std::string& group_name() const { return group_name_; }
-
- private:
- const Type type_;
- std::string trial_name_;
- std::string group_name_;
-
- DISALLOW_COPY_AND_ASSIGN(TestFieldTrialObserver);
-};
-
-std::string MockEscapeQueryParamValue(const std::string& input) {
- return input;
-}
-
-} // namespace
-
-class FieldTrialTest : public ::testing::Test {
- public:
- FieldTrialTest() : trial_list_(nullptr) {}
-
- private:
- MessageLoop message_loop_;
- FieldTrialList trial_list_;
-
- DISALLOW_COPY_AND_ASSIGN(FieldTrialTest);
-};
-
-// Test registration, and also check that destructors are called for trials.
-TEST_F(FieldTrialTest, Registration) {
- const char name1[] = "name 1 test";
- const char name2[] = "name 2 test";
- EXPECT_FALSE(FieldTrialList::Find(name1));
- EXPECT_FALSE(FieldTrialList::Find(name2));
-
- scoped_refptr<FieldTrial> trial1 =
- CreateFieldTrial(name1, 10, "default name 1 test", nullptr);
- EXPECT_EQ(FieldTrial::kNotFinalized, trial1->group_);
- EXPECT_EQ(name1, trial1->trial_name());
- EXPECT_EQ("", trial1->group_name_internal());
-
- trial1->AppendGroup(std::string(), 7);
-
- EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
- EXPECT_FALSE(FieldTrialList::Find(name2));
-
- scoped_refptr<FieldTrial> trial2 =
- CreateFieldTrial(name2, 10, "default name 2 test", nullptr);
- EXPECT_EQ(FieldTrial::kNotFinalized, trial2->group_);
- EXPECT_EQ(name2, trial2->trial_name());
- EXPECT_EQ("", trial2->group_name_internal());
-
- trial2->AppendGroup("a first group", 7);
-
- EXPECT_EQ(trial1.get(), FieldTrialList::Find(name1));
- EXPECT_EQ(trial2.get(), FieldTrialList::Find(name2));
- // Note: FieldTrialList should delete the objects at shutdown.
-}
-
-TEST_F(FieldTrialTest, AbsoluteProbabilities) {
- char always_true[] = " always true";
- char default_always_true[] = " default always true";
- char always_false[] = " always false";
- char default_always_false[] = " default always false";
- for (int i = 1; i < 250; ++i) {
- // Try lots of names, by changing the first character of the name.
- char c = static_cast<char>(i);
- always_true[0] = c;
- default_always_true[0] = c;
- always_false[0] = c;
- default_always_false[0] = c;
-
- scoped_refptr<FieldTrial> trial_true =
- CreateFieldTrial(always_true, 10, default_always_true, nullptr);
- const std::string winner = "TheWinner";
- int winner_group = trial_true->AppendGroup(winner, 10);
-
- EXPECT_EQ(winner_group, trial_true->group());
- EXPECT_EQ(winner, trial_true->group_name());
-
- scoped_refptr<FieldTrial> trial_false =
- CreateFieldTrial(always_false, 10, default_always_false, nullptr);
- int loser_group = trial_false->AppendGroup("ALoser", 0);
-
- EXPECT_NE(loser_group, trial_false->group());
- }
-}
-
-TEST_F(FieldTrialTest, RemainingProbability) {
- // First create a test that hasn't had a winner yet.
- const std::string winner = "Winner";
- const std::string loser = "Loser";
- scoped_refptr<FieldTrial> trial;
- int counter = 0;
- int default_group_number = -1;
- do {
- std::string name = StringPrintf("trial%d", ++counter);
- trial = CreateFieldTrial(name, 10, winner, &default_group_number);
- trial->AppendGroup(loser, 5); // 50% chance of not being chosen.
- // If a group is not assigned, group_ will be kNotFinalized.
- } while (trial->group_ != FieldTrial::kNotFinalized);
-
- // And that 'default' group (winner) should always win.
- EXPECT_EQ(default_group_number, trial->group());
-
- // And that winner should ALWAYS win.
- EXPECT_EQ(winner, trial->group_name());
-}
-
-TEST_F(FieldTrialTest, FiftyFiftyProbability) {
- // Check that even with small divisors, we have the proper probabilities, and
- // all outcomes are possible. Since this is a 50-50 test, it should get both
- // outcomes in a few tries, but we'll try no more than 100 times (and be flaky
- // with probability around 1 in 2^99).
- bool first_winner = false;
- bool second_winner = false;
- int counter = 0;
- do {
- std::string name = StringPrintf("FiftyFifty%d", ++counter);
- std::string default_group_name =
- StringPrintf("Default FiftyFifty%d", ++counter);
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(name, 2, default_group_name, nullptr);
- trial->AppendGroup("first", 1); // 50% chance of being chosen.
- // If group_ is kNotFinalized, then a group assignement hasn't been done.
- if (trial->group_ != FieldTrial::kNotFinalized) {
- first_winner = true;
- continue;
- }
- trial->AppendGroup("second", 1); // Always chosen at this point.
- EXPECT_NE(FieldTrial::kNotFinalized, trial->group());
- second_winner = true;
- } while ((!second_winner || !first_winner) && counter < 100);
- EXPECT_TRUE(second_winner);
- EXPECT_TRUE(first_winner);
-}
-
-TEST_F(FieldTrialTest, MiddleProbabilities) {
- char name[] = " same name";
- char default_group_name[] = " default same name";
- bool false_event_seen = false;
- bool true_event_seen = false;
- for (int i = 1; i < 250; ++i) {
- char c = static_cast<char>(i);
- name[0] = c;
- default_group_name[0] = c;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(name, 10, default_group_name, nullptr);
- int might_win = trial->AppendGroup("MightWin", 5);
-
- if (trial->group() == might_win) {
- true_event_seen = true;
- } else {
- false_event_seen = true;
- }
- if (false_event_seen && true_event_seen)
- return; // Successful test!!!
- }
- // Very surprising to get here. Probability should be around 1 in 2 ** 250.
- // One of the following will fail.
- EXPECT_TRUE(false_event_seen);
- EXPECT_TRUE(true_event_seen);
-}
-
-TEST_F(FieldTrialTest, OneWinner) {
- char name[] = "Some name";
- char default_group_name[] = "Default some name";
- int group_count(10);
-
- int default_group_number = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(name, group_count, default_group_name, nullptr);
- int winner_index(-2);
- std::string winner_name;
-
- for (int i = 1; i <= group_count; ++i) {
- int might_win = trial->AppendGroup(std::string(), 1);
-
- // Because we keep appending groups, we want to see if the last group that
- // was added has been assigned or not.
- if (trial->group_ == might_win) {
- EXPECT_EQ(-2, winner_index);
- winner_index = might_win;
- StringAppendF(&winner_name, "%d", might_win);
- EXPECT_EQ(winner_name, trial->group_name());
- }
- }
- EXPECT_GE(winner_index, 0);
- // Since all groups cover the total probability, we should not have
- // chosen the default group.
- EXPECT_NE(trial->group(), default_group_number);
- EXPECT_EQ(trial->group(), winner_index);
- EXPECT_EQ(trial->group_name(), winner_name);
-}
-
-TEST_F(FieldTrialTest, ActiveGroups) {
- std::string no_group("No Group");
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(no_group, 10, "Default", nullptr);
-
- // There is no winner yet, so no NameGroupId should be returned.
- FieldTrial::ActiveGroup active_group;
- EXPECT_FALSE(trial->GetActiveGroup(&active_group));
-
- // Create a single winning group.
- std::string one_winner("One Winner");
- trial = CreateFieldTrial(one_winner, 10, "Default", nullptr);
- std::string winner("Winner");
- trial->AppendGroup(winner, 10);
- EXPECT_FALSE(trial->GetActiveGroup(&active_group));
- // Finalize the group selection by accessing the selected group.
- trial->group();
- EXPECT_TRUE(trial->GetActiveGroup(&active_group));
- EXPECT_EQ(one_winner, active_group.trial_name);
- EXPECT_EQ(winner, active_group.group_name);
-
- std::string multi_group("MultiGroup");
- scoped_refptr<FieldTrial> multi_group_trial =
- CreateFieldTrial(multi_group, 9, "Default", nullptr);
-
- multi_group_trial->AppendGroup("Me", 3);
- multi_group_trial->AppendGroup("You", 3);
- multi_group_trial->AppendGroup("Them", 3);
- EXPECT_FALSE(multi_group_trial->GetActiveGroup(&active_group));
- // Finalize the group selection by accessing the selected group.
- multi_group_trial->group();
- EXPECT_TRUE(multi_group_trial->GetActiveGroup(&active_group));
- EXPECT_EQ(multi_group, active_group.trial_name);
- EXPECT_EQ(multi_group_trial->group_name(), active_group.group_name);
-
- // Now check if the list is built properly...
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_EQ(2U, active_groups.size());
- for (size_t i = 0; i < active_groups.size(); ++i) {
- // Order is not guaranteed, so check all values.
- EXPECT_NE(no_group, active_groups[i].trial_name);
- EXPECT_TRUE(one_winner != active_groups[i].trial_name ||
- winner == active_groups[i].group_name);
- EXPECT_TRUE(multi_group != active_groups[i].trial_name ||
- multi_group_trial->group_name() == active_groups[i].group_name);
- }
-}
-
-TEST_F(FieldTrialTest, GetActiveFieldTrialGroupsFromString) {
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroupsFromString("*A/X/B/Y/*C/Z",
- &active_groups);
- ASSERT_EQ(2U, active_groups.size());
- EXPECT_EQ("A", active_groups[0].trial_name);
- EXPECT_EQ("X", active_groups[0].group_name);
- EXPECT_EQ("C", active_groups[1].trial_name);
- EXPECT_EQ("Z", active_groups[1].group_name);
-}
-
-TEST_F(FieldTrialTest, ActiveGroupsNotFinalized) {
- const char kTrialName[] = "TestTrial";
- const char kSecondaryGroupName[] = "SecondaryGroup";
-
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
-
- // Before |group()| is called, |GetActiveGroup()| should return false.
- FieldTrial::ActiveGroup active_group;
- EXPECT_FALSE(trial->GetActiveGroup(&active_group));
-
- // |GetActiveFieldTrialGroups()| should also not include the trial.
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_TRUE(active_groups.empty());
-
- // After |group()| has been called, both APIs should succeed.
- const int chosen_group = trial->group();
- EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
-
- EXPECT_TRUE(trial->GetActiveGroup(&active_group));
- EXPECT_EQ(kTrialName, active_group.trial_name);
- if (chosen_group == default_group)
- EXPECT_EQ(kDefaultGroupName, active_group.group_name);
- else
- EXPECT_EQ(kSecondaryGroupName, active_group.group_name);
-
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- ASSERT_EQ(1U, active_groups.size());
- EXPECT_EQ(kTrialName, active_groups[0].trial_name);
- EXPECT_EQ(active_group.group_name, active_groups[0].group_name);
-}
-
-TEST_F(FieldTrialTest, GetGroupNameWithoutActivation) {
- const char kTrialName[] = "TestTrial";
- const char kSecondaryGroupName[] = "SecondaryGroup";
-
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- trial->AppendGroup(kSecondaryGroupName, 50);
-
- // The trial should start inactive.
- EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
-
- // Calling |GetGroupNameWithoutActivation()| should not activate the trial.
- std::string group_name = trial->GetGroupNameWithoutActivation();
- EXPECT_FALSE(group_name.empty());
- EXPECT_FALSE(FieldTrialList::IsTrialActive(kTrialName));
-
- // Calling |group_name()| should activate it and return the same group name.
- EXPECT_EQ(group_name, trial->group_name());
- EXPECT_TRUE(FieldTrialList::IsTrialActive(kTrialName));
-}
-
-TEST_F(FieldTrialTest, Save) {
- std::string save_string;
-
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial("Some name", 10, "Default some name", nullptr);
- // There is no winner yet, so no textual group name is associated with trial.
- // In this case, the trial should not be included.
- EXPECT_EQ("", trial->group_name_internal());
- FieldTrialList::StatesToString(&save_string);
- EXPECT_EQ("", save_string);
- save_string.clear();
-
- // Create a winning group.
- trial->AppendGroup("Winner", 10);
- // Finalize the group selection by accessing the selected group.
- trial->group();
- FieldTrialList::StatesToString(&save_string);
- EXPECT_EQ("Some name/Winner/", save_string);
- save_string.clear();
-
- // Create a second trial and winning group.
- scoped_refptr<FieldTrial> trial2 =
- CreateFieldTrial("xxx", 10, "Default xxx", nullptr);
- trial2->AppendGroup("yyyy", 10);
- // Finalize the group selection by accessing the selected group.
- trial2->group();
-
- FieldTrialList::StatesToString(&save_string);
- // We assume names are alphabetized... though this is not critical.
- EXPECT_EQ("Some name/Winner/xxx/yyyy/", save_string);
- save_string.clear();
-
- // Create a third trial with only the default group.
- scoped_refptr<FieldTrial> trial3 =
- CreateFieldTrial("zzz", 10, "default", nullptr);
- // Finalize the group selection by accessing the selected group.
- trial3->group();
-
- FieldTrialList::StatesToString(&save_string);
- EXPECT_EQ("Some name/Winner/xxx/yyyy/zzz/default/", save_string);
-}
-
-TEST_F(FieldTrialTest, Restore) {
- ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
- ASSERT_FALSE(FieldTrialList::TrialExists("xxx"));
-
- FieldTrialList::CreateTrialsFromString("Some_name/Winner/xxx/yyyy/",
- std::set<std::string>());
-
- FieldTrial* trial = FieldTrialList::Find("Some_name");
- ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
- EXPECT_EQ("Winner", trial->group_name());
- EXPECT_EQ("Some_name", trial->trial_name());
-
- trial = FieldTrialList::Find("xxx");
- ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
- EXPECT_EQ("yyyy", trial->group_name());
- EXPECT_EQ("xxx", trial->trial_name());
-}
-
-TEST_F(FieldTrialTest, RestoreNotEndingWithSlash) {
- EXPECT_TRUE(FieldTrialList::CreateTrialsFromString("tname/gname",
- std::set<std::string>()));
-
- FieldTrial* trial = FieldTrialList::Find("tname");
- ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
- EXPECT_EQ("gname", trial->group_name());
- EXPECT_EQ("tname", trial->trial_name());
-}
-
-TEST_F(FieldTrialTest, BogusRestore) {
- EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingSlash",
- std::set<std::string>()));
- EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("MissingGroupName/",
- std::set<std::string>()));
- EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("noname, only group/",
- std::set<std::string>()));
- EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("/emptyname",
- std::set<std::string>()));
- EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("*/emptyname",
- std::set<std::string>()));
-}
-
-TEST_F(FieldTrialTest, DuplicateRestore) {
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial("Some name", 10, "Default", nullptr);
- trial->AppendGroup("Winner", 10);
- // Finalize the group selection by accessing the selected group.
- trial->group();
- std::string save_string;
- FieldTrialList::StatesToString(&save_string);
- EXPECT_EQ("Some name/Winner/", save_string);
-
- // It is OK if we redundantly specify a winner.
- EXPECT_TRUE(FieldTrialList::CreateTrialsFromString(save_string,
- std::set<std::string>()));
-
- // But it is an error to try to change to a different winner.
- EXPECT_FALSE(FieldTrialList::CreateTrialsFromString("Some name/Loser/",
- std::set<std::string>()));
-}
-
-TEST_F(FieldTrialTest, CreateTrialsFromStringNotActive) {
- ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
- ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
- ASSERT_TRUE(FieldTrialList::CreateTrialsFromString("Abc/def/Xyz/zyx/",
- std::set<std::string>()));
-
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- ASSERT_TRUE(active_groups.empty());
-
- // Check that the values still get returned and querying them activates them.
- EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
- EXPECT_EQ("zyx", FieldTrialList::FindFullName("Xyz"));
-
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- ASSERT_EQ(2U, active_groups.size());
- EXPECT_EQ("Abc", active_groups[0].trial_name);
- EXPECT_EQ("def", active_groups[0].group_name);
- EXPECT_EQ("Xyz", active_groups[1].trial_name);
- EXPECT_EQ("zyx", active_groups[1].group_name);
-}
-
-TEST_F(FieldTrialTest, CreateTrialsFromStringForceActivation) {
- ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
- ASSERT_FALSE(FieldTrialList::TrialExists("def"));
- ASSERT_FALSE(FieldTrialList::TrialExists("Xyz"));
- ASSERT_TRUE(FieldTrialList::CreateTrialsFromString(
- "*Abc/cba/def/fed/*Xyz/zyx/", std::set<std::string>()));
-
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- ASSERT_EQ(2U, active_groups.size());
- EXPECT_EQ("Abc", active_groups[0].trial_name);
- EXPECT_EQ("cba", active_groups[0].group_name);
- EXPECT_EQ("Xyz", active_groups[1].trial_name);
- EXPECT_EQ("zyx", active_groups[1].group_name);
-}
-
-TEST_F(FieldTrialTest, CreateTrialsFromStringNotActiveObserver) {
- ASSERT_FALSE(FieldTrialList::TrialExists("Abc"));
-
- TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
- ASSERT_TRUE(FieldTrialList::CreateTrialsFromString("Abc/def/",
- std::set<std::string>()));
- RunLoop().RunUntilIdle();
- // Observer shouldn't be notified.
- EXPECT_TRUE(observer.trial_name().empty());
-
- // Check that the values still get returned and querying them activates them.
- EXPECT_EQ("def", FieldTrialList::FindFullName("Abc"));
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ("Abc", observer.trial_name());
- EXPECT_EQ("def", observer.group_name());
-}
-
-TEST_F(FieldTrialTest, CreateTrialsFromStringWithIgnoredFieldTrials) {
- ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted1"));
- ASSERT_FALSE(FieldTrialList::TrialExists("Foo"));
- ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted2"));
- ASSERT_FALSE(FieldTrialList::TrialExists("Bar"));
- ASSERT_FALSE(FieldTrialList::TrialExists("Unaccepted3"));
-
- std::set<std::string> ignored_trial_names;
- ignored_trial_names.insert("Unaccepted1");
- ignored_trial_names.insert("Unaccepted2");
- ignored_trial_names.insert("Unaccepted3");
-
- FieldTrialList::CreateTrialsFromString(
- "Unaccepted1/Unaccepted1_name/"
- "Foo/Foo_name/"
- "Unaccepted2/Unaccepted2_name/"
- "Bar/Bar_name/"
- "Unaccepted3/Unaccepted3_name/",
- ignored_trial_names);
-
- EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted1"));
- EXPECT_TRUE(FieldTrialList::TrialExists("Foo"));
- EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted2"));
- EXPECT_TRUE(FieldTrialList::TrialExists("Bar"));
- EXPECT_FALSE(FieldTrialList::TrialExists("Unaccepted3"));
-
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_TRUE(active_groups.empty());
-
- FieldTrial* trial = FieldTrialList::Find("Foo");
- ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
- EXPECT_EQ("Foo", trial->trial_name());
- EXPECT_EQ("Foo_name", trial->group_name());
-
- trial = FieldTrialList::Find("Bar");
- ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
- EXPECT_EQ("Bar", trial->trial_name());
- EXPECT_EQ("Bar_name", trial->group_name());
-}
-
-TEST_F(FieldTrialTest, CreateFieldTrial) {
- ASSERT_FALSE(FieldTrialList::TrialExists("Some_name"));
-
- FieldTrialList::CreateFieldTrial("Some_name", "Winner");
-
- FieldTrial* trial = FieldTrialList::Find("Some_name");
- ASSERT_NE(static_cast<FieldTrial*>(nullptr), trial);
- EXPECT_EQ("Winner", trial->group_name());
- EXPECT_EQ("Some_name", trial->trial_name());
-}
-
-TEST_F(FieldTrialTest, CreateFieldTrialIsNotActive) {
- const char kTrialName[] = "CreateFieldTrialIsActiveTrial";
- const char kWinnerGroup[] = "Winner";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
- FieldTrialList::CreateFieldTrial(kTrialName, kWinnerGroup);
-
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_TRUE(active_groups.empty());
-}
-
-TEST_F(FieldTrialTest, DuplicateFieldTrial) {
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial("Some_name", 10, "Default", nullptr);
- trial->AppendGroup("Winner", 10);
-
- // It is OK if we redundantly specify a winner.
- FieldTrial* trial1 = FieldTrialList::CreateFieldTrial("Some_name", "Winner");
- EXPECT_TRUE(trial1 != nullptr);
-
- // But it is an error to try to change to a different winner.
- FieldTrial* trial2 = FieldTrialList::CreateFieldTrial("Some_name", "Loser");
- EXPECT_TRUE(trial2 == nullptr);
-}
-
-TEST_F(FieldTrialTest, DisableImmediately) {
- int default_group_number = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial("trial", 100, "default", &default_group_number);
- trial->Disable();
- ASSERT_EQ("default", trial->group_name());
- ASSERT_EQ(default_group_number, trial->group());
-}
-
-TEST_F(FieldTrialTest, DisableAfterInitialization) {
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial("trial", 100, "default", nullptr);
- trial->AppendGroup("non_default", 100);
- trial->Disable();
- ASSERT_EQ("default", trial->group_name());
-}
-
-TEST_F(FieldTrialTest, ForcedFieldTrials) {
- // Validate we keep the forced choice.
- FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Use the",
- "Force");
- EXPECT_STREQ("Force", forced_trial->group_name().c_str());
-
- int default_group_number = -1;
- scoped_refptr<FieldTrial> factory_trial =
- CreateFieldTrial("Use the", 1000, "default", &default_group_number);
- EXPECT_EQ(factory_trial.get(), forced_trial);
-
- int chosen_group = factory_trial->AppendGroup("Force", 100);
- EXPECT_EQ(chosen_group, factory_trial->group());
- int not_chosen_group = factory_trial->AppendGroup("Dark Side", 100);
- EXPECT_NE(chosen_group, not_chosen_group);
-
- // Since we didn't force the default group, we should not be returned the
- // chosen group as the default group.
- EXPECT_NE(default_group_number, chosen_group);
- int new_group = factory_trial->AppendGroup("Duck Tape", 800);
- EXPECT_NE(chosen_group, new_group);
- // The new group should not be the default group either.
- EXPECT_NE(default_group_number, new_group);
-}
-
-TEST_F(FieldTrialTest, ForcedFieldTrialsDefaultGroup) {
- // Forcing the default should use the proper group ID.
- FieldTrial* forced_trial = FieldTrialList::CreateFieldTrial("Trial Name",
- "Default");
- int default_group_number = -1;
- scoped_refptr<FieldTrial> factory_trial =
- CreateFieldTrial("Trial Name", 1000, "Default", &default_group_number);
- EXPECT_EQ(forced_trial, factory_trial.get());
-
- int other_group = factory_trial->AppendGroup("Not Default", 100);
- EXPECT_STREQ("Default", factory_trial->group_name().c_str());
- EXPECT_EQ(default_group_number, factory_trial->group());
- EXPECT_NE(other_group, factory_trial->group());
-
- int new_other_group = factory_trial->AppendGroup("Not Default Either", 800);
- EXPECT_NE(new_other_group, factory_trial->group());
-}
-
-TEST_F(FieldTrialTest, SetForced) {
- // Start by setting a trial for which we ensure a winner...
- int default_group_number = -1;
- scoped_refptr<FieldTrial> forced_trial =
- CreateFieldTrial("Use the", 1, "default", &default_group_number);
- EXPECT_EQ(forced_trial, forced_trial);
-
- int forced_group = forced_trial->AppendGroup("Force", 1);
- EXPECT_EQ(forced_group, forced_trial->group());
-
- // Now force it.
- forced_trial->SetForced();
-
- // Now try to set it up differently as a hard coded registration would.
- scoped_refptr<FieldTrial> hard_coded_trial =
- CreateFieldTrial("Use the", 1, "default", &default_group_number);
- EXPECT_EQ(hard_coded_trial, forced_trial);
-
- int would_lose_group = hard_coded_trial->AppendGroup("Force", 0);
- EXPECT_EQ(forced_group, hard_coded_trial->group());
- EXPECT_EQ(forced_group, would_lose_group);
-
- // Same thing if we would have done it to win again.
- scoped_refptr<FieldTrial> other_hard_coded_trial =
- CreateFieldTrial("Use the", 1, "default", &default_group_number);
- EXPECT_EQ(other_hard_coded_trial, forced_trial);
-
- int would_win_group = other_hard_coded_trial->AppendGroup("Force", 1);
- EXPECT_EQ(forced_group, other_hard_coded_trial->group());
- EXPECT_EQ(forced_group, would_win_group);
-}
-
-TEST_F(FieldTrialTest, SetForcedDefaultOnly) {
- const char kTrialName[] = "SetForcedDefaultOnly";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- trial->SetForced();
-
- trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
- EXPECT_EQ(default_group, trial->group());
- EXPECT_EQ(kDefaultGroupName, trial->group_name());
-}
-
-TEST_F(FieldTrialTest, SetForcedDefaultWithExtraGroup) {
- const char kTrialName[] = "SetForcedDefaultWithExtraGroup";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- trial->SetForced();
-
- trial = CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
- const int extra_group = trial->AppendGroup("Extra", 100);
- EXPECT_EQ(default_group, trial->group());
- EXPECT_NE(extra_group, trial->group());
- EXPECT_EQ(kDefaultGroupName, trial->group_name());
-}
-
-TEST_F(FieldTrialTest, SetForcedTurnFeatureOn) {
- const char kTrialName[] = "SetForcedTurnFeatureOn";
- const char kExtraGroupName[] = "Extra";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- // Simulate a server-side (forced) config that turns the feature on when the
- // original hard-coded config had it disabled.
- scoped_refptr<FieldTrial> forced_trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
- forced_trial->AppendGroup(kExtraGroupName, 100);
- forced_trial->SetForced();
-
- int default_group = -1;
- scoped_refptr<FieldTrial> client_trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- const int extra_group = client_trial->AppendGroup(kExtraGroupName, 0);
- EXPECT_NE(default_group, extra_group);
-
- EXPECT_FALSE(client_trial->group_reported_);
- EXPECT_EQ(extra_group, client_trial->group());
- EXPECT_TRUE(client_trial->group_reported_);
- EXPECT_EQ(kExtraGroupName, client_trial->group_name());
-}
-
-TEST_F(FieldTrialTest, SetForcedTurnFeatureOff) {
- const char kTrialName[] = "SetForcedTurnFeatureOff";
- const char kExtraGroupName[] = "Extra";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- // Simulate a server-side (forced) config that turns the feature off when the
- // original hard-coded config had it enabled.
- scoped_refptr<FieldTrial> forced_trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
- forced_trial->AppendGroup(kExtraGroupName, 0);
- forced_trial->SetForced();
-
- int default_group = -1;
- scoped_refptr<FieldTrial> client_trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- const int extra_group = client_trial->AppendGroup(kExtraGroupName, 100);
- EXPECT_NE(default_group, extra_group);
-
- EXPECT_FALSE(client_trial->group_reported_);
- EXPECT_EQ(default_group, client_trial->group());
- EXPECT_TRUE(client_trial->group_reported_);
- EXPECT_EQ(kDefaultGroupName, client_trial->group_name());
-}
-
-TEST_F(FieldTrialTest, SetForcedChangeDefault_Default) {
- const char kTrialName[] = "SetForcedDefaultGroupChange";
- const char kGroupAName[] = "A";
- const char kGroupBName[] = "B";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- // Simulate a server-side (forced) config that switches which group is default
- // and ensures that the non-forced code receives the correct group numbers.
- scoped_refptr<FieldTrial> forced_trial =
- CreateFieldTrial(kTrialName, 100, kGroupAName, nullptr);
- forced_trial->AppendGroup(kGroupBName, 100);
- forced_trial->SetForced();
-
- int default_group = -1;
- scoped_refptr<FieldTrial> client_trial =
- CreateFieldTrial(kTrialName, 100, kGroupBName, &default_group);
- const int extra_group = client_trial->AppendGroup(kGroupAName, 50);
- EXPECT_NE(default_group, extra_group);
-
- EXPECT_FALSE(client_trial->group_reported_);
- EXPECT_EQ(default_group, client_trial->group());
- EXPECT_TRUE(client_trial->group_reported_);
- EXPECT_EQ(kGroupBName, client_trial->group_name());
-}
-
-TEST_F(FieldTrialTest, SetForcedChangeDefault_NonDefault) {
- const char kTrialName[] = "SetForcedDefaultGroupChange";
- const char kGroupAName[] = "A";
- const char kGroupBName[] = "B";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- // Simulate a server-side (forced) config that switches which group is default
- // and ensures that the non-forced code receives the correct group numbers.
- scoped_refptr<FieldTrial> forced_trial =
- CreateFieldTrial(kTrialName, 100, kGroupAName, nullptr);
- forced_trial->AppendGroup(kGroupBName, 0);
- forced_trial->SetForced();
-
- int default_group = -1;
- scoped_refptr<FieldTrial> client_trial =
- CreateFieldTrial(kTrialName, 100, kGroupBName, &default_group);
- const int extra_group = client_trial->AppendGroup(kGroupAName, 50);
- EXPECT_NE(default_group, extra_group);
-
- EXPECT_FALSE(client_trial->group_reported_);
- EXPECT_EQ(extra_group, client_trial->group());
- EXPECT_TRUE(client_trial->group_reported_);
- EXPECT_EQ(kGroupAName, client_trial->group_name());
-}
-
-TEST_F(FieldTrialTest, Observe) {
- const char kTrialName[] = "TrialToObserve1";
- const char kSecondaryGroupName[] = "SecondaryGroup";
-
- TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
- const int chosen_group = trial->group();
- EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
-
- // Observers are called asynchronously.
- EXPECT_TRUE(observer.trial_name().empty());
- EXPECT_TRUE(observer.group_name().empty());
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(kTrialName, observer.trial_name());
- if (chosen_group == default_group)
- EXPECT_EQ(kDefaultGroupName, observer.group_name());
- else
- EXPECT_EQ(kSecondaryGroupName, observer.group_name());
-}
-
-TEST_F(FieldTrialTest, SynchronousObserver) {
- const char kTrialName[] = "TrialToObserve1";
- const char kSecondaryGroupName[] = "SecondaryGroup";
-
- TestFieldTrialObserver observer(TestFieldTrialObserver::SYNCHRONOUS);
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- const int secondary_group = trial->AppendGroup(kSecondaryGroupName, 50);
- const int chosen_group = trial->group();
- EXPECT_TRUE(chosen_group == default_group || chosen_group == secondary_group);
-
- // The observer should be notified synchronously by the group() call.
- EXPECT_EQ(kTrialName, observer.trial_name());
- if (chosen_group == default_group)
- EXPECT_EQ(kDefaultGroupName, observer.group_name());
- else
- EXPECT_EQ(kSecondaryGroupName, observer.group_name());
-}
-
-TEST_F(FieldTrialTest, ObserveDisabled) {
- const char kTrialName[] = "TrialToObserve2";
-
- TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- trial->AppendGroup("A", 25);
- trial->AppendGroup("B", 25);
- trial->AppendGroup("C", 25);
- trial->Disable();
-
- // Observer shouldn't be notified of a disabled trial.
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(observer.trial_name().empty());
- EXPECT_TRUE(observer.group_name().empty());
-
- // Observer shouldn't be notified even after a |group()| call.
- EXPECT_EQ(default_group, trial->group());
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(observer.trial_name().empty());
- EXPECT_TRUE(observer.group_name().empty());
-}
-
-TEST_F(FieldTrialTest, ObserveForcedDisabled) {
- const char kTrialName[] = "TrialToObserve3";
-
- TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
- int default_group = -1;
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, &default_group);
- trial->AppendGroup("A", 25);
- trial->AppendGroup("B", 25);
- trial->AppendGroup("C", 25);
- trial->SetForced();
- trial->Disable();
-
- // Observer shouldn't be notified of a disabled trial, even when forced.
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(observer.trial_name().empty());
- EXPECT_TRUE(observer.group_name().empty());
-
- // Observer shouldn't be notified even after a |group()| call.
- EXPECT_EQ(default_group, trial->group());
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(observer.trial_name().empty());
- EXPECT_TRUE(observer.group_name().empty());
-}
-
-TEST_F(FieldTrialTest, DisabledTrialNotActive) {
- const char kTrialName[] = "DisabledTrial";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, 100, kDefaultGroupName, nullptr);
- trial->AppendGroup("X", 50);
- trial->Disable();
-
- // Ensure the trial is not listed as active.
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_TRUE(active_groups.empty());
-
- // Ensure the trial is not listed in the |StatesToString()| result.
- std::string states;
- FieldTrialList::StatesToString(&states);
- EXPECT_TRUE(states.empty());
-}
-
-TEST_F(FieldTrialTest, ExpirationYearNotExpired) {
- const char kTrialName[] = "NotExpired";
- const char kGroupName[] = "Group2";
- const int kProbability = 100;
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial(kTrialName, kProbability, kDefaultGroupName, nullptr);
- trial->AppendGroup(kGroupName, kProbability);
- EXPECT_EQ(kGroupName, trial->group_name());
-}
-
-TEST_F(FieldTrialTest, FloatBoundariesGiveEqualGroupSizes) {
- const int kBucketCount = 100;
-
- // Try each boundary value |i / 100.0| as the entropy value.
- for (int i = 0; i < kBucketCount; ++i) {
- const double entropy = i / static_cast<double>(kBucketCount);
-
- scoped_refptr<FieldTrial> trial(
- new FieldTrial("test", kBucketCount, "default", entropy));
- for (int j = 0; j < kBucketCount; ++j)
- trial->AppendGroup(IntToString(j), 1);
-
- EXPECT_EQ(IntToString(i), trial->group_name());
- }
-}
-
-TEST_F(FieldTrialTest, DoesNotSurpassTotalProbability) {
- const double kEntropyValue = 1.0 - 1e-9;
- ASSERT_LT(kEntropyValue, 1.0);
-
- scoped_refptr<FieldTrial> trial(
- new FieldTrial("test", 2, "default", kEntropyValue));
- trial->AppendGroup("1", 1);
- trial->AppendGroup("2", 1);
-
- EXPECT_EQ("2", trial->group_name());
-}
-
-TEST_F(FieldTrialTest, CreateSimulatedFieldTrial) {
- const char kTrialName[] = "CreateSimulatedFieldTrial";
- ASSERT_FALSE(FieldTrialList::TrialExists(kTrialName));
-
- // Different cases to test, e.g. default vs. non default group being chosen.
- struct {
- double entropy_value;
- const char* expected_group;
- } test_cases[] = {
- { 0.4, "A" },
- { 0.85, "B" },
- { 0.95, kDefaultGroupName },
- };
-
- for (size_t i = 0; i < arraysize(test_cases); ++i) {
- TestFieldTrialObserver observer(TestFieldTrialObserver::ASYNCHRONOUS);
- scoped_refptr<FieldTrial> trial(
- FieldTrial::CreateSimulatedFieldTrial(kTrialName, 100, kDefaultGroupName,
- test_cases[i].entropy_value));
- trial->AppendGroup("A", 80);
- trial->AppendGroup("B", 10);
- EXPECT_EQ(test_cases[i].expected_group, trial->group_name());
-
- // Field trial shouldn't have been registered with the list.
- EXPECT_FALSE(FieldTrialList::TrialExists(kTrialName));
- EXPECT_EQ(0u, FieldTrialList::GetFieldTrialCount());
-
- // Observer shouldn't have been notified.
- RunLoop().RunUntilIdle();
- EXPECT_TRUE(observer.trial_name().empty());
-
- // The trial shouldn't be in the active set of trials.
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_TRUE(active_groups.empty());
-
- // The trial shouldn't be listed in the |StatesToString()| result.
- std::string states;
- FieldTrialList::StatesToString(&states);
- EXPECT_TRUE(states.empty());
- }
-}
-
-TEST(FieldTrialTestWithoutList, StatesStringFormat) {
- std::string save_string;
-
- // Scoping the first FieldTrialList, as we need another one to test the
- // importing function.
- {
- FieldTrialList field_trial_list(nullptr);
- scoped_refptr<FieldTrial> trial =
- CreateFieldTrial("Abc", 10, "Default some name", nullptr);
- trial->AppendGroup("cba", 10);
- trial->group();
- scoped_refptr<FieldTrial> trial2 =
- CreateFieldTrial("Xyz", 10, "Default xxx", nullptr);
- trial2->AppendGroup("zyx", 10);
- trial2->group();
- scoped_refptr<FieldTrial> trial3 =
- CreateFieldTrial("zzz", 10, "default", nullptr);
-
- FieldTrialList::AllStatesToString(&save_string, false);
- }
-
- // Starting with a new blank FieldTrialList.
- FieldTrialList field_trial_list(nullptr);
- ASSERT_TRUE(field_trial_list.CreateTrialsFromString(save_string,
- std::set<std::string>()));
-
- FieldTrial::ActiveGroups active_groups;
- field_trial_list.GetActiveFieldTrialGroups(&active_groups);
- ASSERT_EQ(2U, active_groups.size());
- EXPECT_EQ("Abc", active_groups[0].trial_name);
- EXPECT_EQ("cba", active_groups[0].group_name);
- EXPECT_EQ("Xyz", active_groups[1].trial_name);
- EXPECT_EQ("zyx", active_groups[1].group_name);
- EXPECT_TRUE(field_trial_list.TrialExists("zzz"));
-}
-
-TEST(FieldTrialDeathTest, OneTimeRandomizedTrialWithoutFieldTrialList) {
- // Trying to instantiate a one-time randomized field trial before the
- // FieldTrialList is created should crash.
- EXPECT_DEATH_IF_SUPPORTED(
- FieldTrialList::FactoryGetFieldTrial(
- "OneTimeRandomizedTrialWithoutFieldTrialList", 100, kDefaultGroupName,
- FieldTrialList::kNoExpirationYear, 1, 1,
- FieldTrial::ONE_TIME_RANDOMIZED, nullptr),
- "");
-}
-
-TEST(FieldTrialListTest, TestCopyFieldTrialStateToFlags) {
- constexpr char kFieldTrialHandleSwitch[] = "test-field-trial-handle";
- constexpr char kEnableFeaturesSwitch[] = "test-enable-features";
- constexpr char kDisableFeaturesSwitch[] = "test-disable-features";
-
- FieldTrialList field_trial_list(std::make_unique<MockEntropyProvider>());
-
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine("A,B", "C");
-
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("Trial1", "Group1");
- feature_list->RegisterFieldTrialOverride(
- "MyFeature", FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
-
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.InitWithFeatureList(std::move(feature_list));
-
- FilePath test_file_path = FilePath(FILE_PATH_LITERAL("Program"));
- CommandLine command_line = CommandLine(test_file_path);
-
- FieldTrialList::CopyFieldTrialStateToFlags(
- kFieldTrialHandleSwitch, kEnableFeaturesSwitch, kDisableFeaturesSwitch,
- &command_line);
- EXPECT_TRUE(command_line.HasSwitch(kFieldTrialHandleSwitch));
-
- // Explictly specified enabled/disabled features should be specified.
- EXPECT_EQ("A,B", command_line.GetSwitchValueASCII(kEnableFeaturesSwitch));
- EXPECT_EQ("C", command_line.GetSwitchValueASCII(kDisableFeaturesSwitch));
-}
-
-TEST(FieldTrialListTest, InstantiateAllocator) {
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.Init();
-
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial("Trial1", "Group1");
-
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
- void* memory = field_trial_list.field_trial_allocator_->shared_memory();
- size_t used = field_trial_list.field_trial_allocator_->used();
-
- // Ensure that the function is idempotent.
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
- void* new_memory = field_trial_list.field_trial_allocator_->shared_memory();
- size_t new_used = field_trial_list.field_trial_allocator_->used();
- EXPECT_EQ(memory, new_memory);
- EXPECT_EQ(used, new_used);
-}
-
-TEST(FieldTrialListTest, AddTrialsToAllocator) {
- std::string save_string;
- SharedMemoryHandle handle;
-
- // Scoping the first FieldTrialList, as we need another one to test that it
- // matches.
- {
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.Init();
-
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial("Trial1", "Group1");
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
- FieldTrialList::AllStatesToString(&save_string, false);
- handle = SharedMemory::DuplicateHandle(
- field_trial_list.field_trial_allocator_->shared_memory()->handle());
- }
-
- FieldTrialList field_trial_list2(nullptr);
- std::unique_ptr<SharedMemory> shm(new SharedMemory(handle, true));
- // 4 KiB is enough to hold the trials only created for this test.
- shm.get()->Map(4 << 10);
- FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
- std::string check_string;
- FieldTrialList::AllStatesToString(&check_string, false);
- EXPECT_EQ(save_string, check_string);
-}
-
-TEST(FieldTrialListTest, DoNotAddSimulatedFieldTrialsToAllocator) {
- constexpr char kTrialName[] = "trial";
- SharedMemoryHandle handle;
- {
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.Init();
-
- // Create a simulated trial and a real trial and call group() on them, which
- // should only add the real trial to the field trial allocator.
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
-
- // This shouldn't add to the allocator.
- scoped_refptr<FieldTrial> simulated_trial =
- FieldTrial::CreateSimulatedFieldTrial(kTrialName, 100, "Simulated",
- 0.95);
- simulated_trial->group();
-
- // This should add to the allocator.
- FieldTrial* real_trial =
- FieldTrialList::CreateFieldTrial(kTrialName, "Real");
- real_trial->group();
-
- handle = SharedMemory::DuplicateHandle(
- field_trial_list.field_trial_allocator_->shared_memory()->handle());
- }
-
- // Check that there's only one entry in the allocator.
- FieldTrialList field_trial_list2(nullptr);
- std::unique_ptr<SharedMemory> shm(new SharedMemory(handle, true));
- // 4 KiB is enough to hold the trials only created for this test.
- shm.get()->Map(4 << 10);
- FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
- std::string check_string;
- FieldTrialList::AllStatesToString(&check_string, false);
- ASSERT_EQ(check_string.find("Simulated"), std::string::npos);
-}
-
-TEST(FieldTrialListTest, AssociateFieldTrialParams) {
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.Init();
-
- std::string trial_name("Trial1");
- std::string group_name("Group1");
-
- // Create a field trial with some params.
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial(trial_name, group_name);
- std::map<std::string, std::string> params;
- params["key1"] = "value1";
- params["key2"] = "value2";
- FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
- trial_name, group_name, params);
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
-
- // Clear all cached params from the associator.
- FieldTrialParamAssociator::GetInstance()->ClearAllCachedParamsForTesting();
- // Check that the params have been cleared from the cache.
- std::map<std::string, std::string> cached_params;
- FieldTrialParamAssociator::GetInstance()->GetFieldTrialParamsWithoutFallback(
- trial_name, group_name, &cached_params);
- EXPECT_EQ(0U, cached_params.size());
-
- // Check that we fetch the param from shared memory properly.
- std::map<std::string, std::string> new_params;
- FieldTrialParamAssociator::GetInstance()->GetFieldTrialParams(trial_name,
- &new_params);
- EXPECT_EQ("value1", new_params["key1"]);
- EXPECT_EQ("value2", new_params["key2"]);
- EXPECT_EQ(2U, new_params.size());
-}
-
-TEST(FieldTrialListTest, ClearParamsFromSharedMemory) {
- std::string trial_name("Trial1");
- std::string group_name("Group1");
-
- SharedMemoryHandle handle;
- {
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.Init();
-
- // Create a field trial with some params.
- FieldTrialList field_trial_list(nullptr);
- FieldTrial* trial =
- FieldTrialList::CreateFieldTrial(trial_name, group_name);
- std::map<std::string, std::string> params;
- params["key1"] = "value1";
- params["key2"] = "value2";
- FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
- trial_name, group_name, params);
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
-
- // Clear all params from the associator AND shared memory. The allocated
- // segments should be different.
- FieldTrial::FieldTrialRef old_ref = trial->ref_;
- FieldTrialParamAssociator::GetInstance()->ClearAllParamsForTesting();
- FieldTrial::FieldTrialRef new_ref = trial->ref_;
- EXPECT_NE(old_ref, new_ref);
-
- // Check that there are no params associated with the field trial anymore.
- std::map<std::string, std::string> new_params;
- FieldTrialParamAssociator::GetInstance()->GetFieldTrialParams(trial_name,
- &new_params);
- EXPECT_EQ(0U, new_params.size());
-
- // Now duplicate the handle so we can easily check that the trial is still
- // in shared memory via AllStatesToString.
- handle = SharedMemory::DuplicateHandle(
- field_trial_list.field_trial_allocator_->shared_memory()->handle());
- }
-
- // Check that we have the trial.
- FieldTrialList field_trial_list2(nullptr);
- std::unique_ptr<SharedMemory> shm(new SharedMemory(handle, true));
- // 4 KiB is enough to hold the trials only created for this test.
- shm.get()->Map(4 << 10);
- FieldTrialList::CreateTrialsFromSharedMemory(std::move(shm));
- std::string check_string;
- FieldTrialList::AllStatesToString(&check_string, false);
- EXPECT_EQ("*Trial1/Group1/", check_string);
-}
-
-TEST(FieldTrialListTest, DumpAndFetchFromSharedMemory) {
- std::string trial_name("Trial1");
- std::string group_name("Group1");
-
- // Create a field trial with some params.
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial(trial_name, group_name);
- std::map<std::string, std::string> params;
- params["key1"] = "value1";
- params["key2"] = "value2";
- FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
- trial_name, group_name, params);
-
- std::unique_ptr<SharedMemory> shm(new SharedMemory());
- // 4 KiB is enough to hold the trials only created for this test.
- shm.get()->CreateAndMapAnonymous(4 << 10);
- // We _could_ use PersistentMemoryAllocator, this just has less params.
- SharedPersistentMemoryAllocator allocator(std::move(shm), 1, "", false);
-
- // Dump and subsequently retrieve the field trial to |allocator|.
- FieldTrialList::DumpAllFieldTrialsToPersistentAllocator(&allocator);
- std::vector<const FieldTrial::FieldTrialEntry*> entries =
- FieldTrialList::GetAllFieldTrialsFromPersistentAllocator(allocator);
-
- // Check that we have the entry we put in.
- EXPECT_EQ(1u, entries.size());
- const FieldTrial::FieldTrialEntry* entry = entries[0];
-
- // Check that the trial and group names match.
- StringPiece shm_trial_name;
- StringPiece shm_group_name;
- entry->GetTrialAndGroupName(&shm_trial_name, &shm_group_name);
- EXPECT_EQ(trial_name, shm_trial_name);
- EXPECT_EQ(group_name, shm_group_name);
-
- // Check that the params match.
- std::map<std::string, std::string> shm_params;
- entry->GetParams(&shm_params);
- EXPECT_EQ(2u, shm_params.size());
- EXPECT_EQ("value1", shm_params["key1"]);
- EXPECT_EQ("value2", shm_params["key2"]);
-}
-
-#if !defined(OS_NACL)
-TEST(FieldTrialListTest, SerializeSharedMemoryHandleMetadata) {
- std::unique_ptr<SharedMemory> shm(new SharedMemory());
- shm->CreateAndMapAnonymous(4 << 10);
-
- std::string serialized =
- FieldTrialList::SerializeSharedMemoryHandleMetadata(shm->handle());
-#if defined(OS_WIN) || defined(OS_FUCHSIA)
- SharedMemoryHandle deserialized =
- FieldTrialList::DeserializeSharedMemoryHandleMetadata(serialized);
-#else
- // Use a valid-looking arbitrary number for the file descriptor. It's not
- // being used in this unittest, but needs to pass sanity checks in the
- // handle's constructor.
- SharedMemoryHandle deserialized =
- FieldTrialList::DeserializeSharedMemoryHandleMetadata(42, serialized);
-#endif
- EXPECT_EQ(deserialized.GetGUID(), shm->handle().GetGUID());
- EXPECT_FALSE(deserialized.GetGUID().is_empty());
-}
-#endif // !defined(OS_NACL)
-
-// Verify that the field trial shared memory handle is really read-only, and
-// does not allow writable mappings. Test disabled on NaCl, Windows and Fuchsia
-// which don't support/implement GetFieldTrialHandle(). For Fuchsia, see
-// crbug.com/752368
-#if !defined(OS_NACL) && !defined(OS_WIN) && !defined(OS_FUCHSIA)
-TEST(FieldTrialListTest, CheckReadOnlySharedMemoryHandle) {
- FieldTrialList field_trial_list(nullptr);
- FieldTrialList::CreateFieldTrial("Trial1", "Group1");
-
- test::ScopedFeatureList scoped_feature_list;
- scoped_feature_list.Init();
-
- FieldTrialList::InstantiateFieldTrialAllocatorIfNeeded();
-
- SharedMemoryHandle handle = FieldTrialList::GetFieldTrialHandle();
- ASSERT_TRUE(handle.IsValid());
-
- ASSERT_TRUE(CheckReadOnlySharedMemoryHandleForTesting(handle));
-}
-#endif // !OS_NACL && !OS_WIN && !OS_FUCHSIA
-
-TEST_F(FieldTrialTest, TestAllParamsToString) {
- std::string exptected_output = "t1.g1:p1/v1/p2/v2";
-
- // Create study with one group and two params.
- std::map<std::string, std::string> params;
- params["p1"] = "v1";
- params["p2"] = "v2";
- FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
- "t1", "g1", params);
- EXPECT_EQ(
- "", FieldTrialList::AllParamsToString(false, &MockEscapeQueryParamValue));
-
- scoped_refptr<FieldTrial> trial1 =
- CreateFieldTrial("t1", 100, "Default", nullptr);
- trial1->AppendGroup("g1", 100);
- trial1->group();
- EXPECT_EQ(exptected_output, FieldTrialList::AllParamsToString(
- false, &MockEscapeQueryParamValue));
-
- // Create study with two groups and params that don't belog to the assigned
- // group. This should be in the output.
- FieldTrialParamAssociator::GetInstance()->AssociateFieldTrialParams(
- "t2", "g2", params);
- scoped_refptr<FieldTrial> trial2 =
- CreateFieldTrial("t2", 100, "Default", nullptr);
- trial2->AppendGroup("g1", 100);
- trial2->AppendGroup("g2", 0);
- trial2->group();
- EXPECT_EQ(exptected_output, FieldTrialList::AllParamsToString(
- false, &MockEscapeQueryParamValue));
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_base_unittest.cc b/base/metrics/histogram_base_unittest.cc
deleted file mode 100644
index e539e5c..0000000
--- a/base/metrics/histogram_base_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 <vector>
-
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/sample_vector.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/pickle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class HistogramBaseTest : public testing::Test {
- protected:
- HistogramBaseTest() {
- // Each test will have a clean state (no Histogram / BucketRanges
- // registered).
- ResetStatisticsRecorder();
- }
-
- ~HistogramBaseTest() override = default;
-
- void ResetStatisticsRecorder() {
- // It is necessary to fully destruct any existing StatisticsRecorder
- // before creating a new one.
- statistics_recorder_.reset();
- statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
- }
-
- private:
- std::unique_ptr<StatisticsRecorder> statistics_recorder_;
-
- DISALLOW_COPY_AND_ASSIGN(HistogramBaseTest);
-};
-
-TEST_F(HistogramBaseTest, DeserializeHistogram) {
- HistogramBase* histogram = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10,
- (HistogramBase::kUmaTargetedHistogramFlag |
- HistogramBase::kIPCSerializationSourceFlag));
-
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
- HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
- EXPECT_EQ(histogram, deserialized);
-
- ResetStatisticsRecorder();
-
- PickleIterator iter2(pickle);
- deserialized = DeserializeHistogramInfo(&iter2);
- EXPECT_TRUE(deserialized);
- EXPECT_NE(histogram, deserialized);
- EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
- EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
-
- // kIPCSerializationSourceFlag will be cleared.
- EXPECT_EQ(HistogramBase::kUmaTargetedHistogramFlag, deserialized->flags());
-}
-
-TEST_F(HistogramBaseTest, DeserializeLinearHistogram) {
- HistogramBase* histogram = LinearHistogram::FactoryGet(
- "TestHistogram", 1, 1000, 10,
- HistogramBase::kIPCSerializationSourceFlag);
-
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
- HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
- EXPECT_EQ(histogram, deserialized);
-
- ResetStatisticsRecorder();
-
- PickleIterator iter2(pickle);
- deserialized = DeserializeHistogramInfo(&iter2);
- EXPECT_TRUE(deserialized);
- EXPECT_NE(histogram, deserialized);
- EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
- EXPECT_TRUE(deserialized->HasConstructionArguments(1, 1000, 10));
- EXPECT_EQ(0, deserialized->flags());
-}
-
-TEST_F(HistogramBaseTest, DeserializeBooleanHistogram) {
- HistogramBase* histogram = BooleanHistogram::FactoryGet(
- "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
-
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
- HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
- EXPECT_EQ(histogram, deserialized);
-
- ResetStatisticsRecorder();
-
- PickleIterator iter2(pickle);
- deserialized = DeserializeHistogramInfo(&iter2);
- EXPECT_TRUE(deserialized);
- EXPECT_NE(histogram, deserialized);
- EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
- EXPECT_TRUE(deserialized->HasConstructionArguments(1, 2, 3));
- EXPECT_EQ(0, deserialized->flags());
-}
-
-TEST_F(HistogramBaseTest, DeserializeCustomHistogram) {
- std::vector<HistogramBase::Sample> ranges;
- ranges.push_back(13);
- ranges.push_back(5);
- ranges.push_back(9);
-
- HistogramBase* histogram = CustomHistogram::FactoryGet(
- "TestHistogram", ranges, HistogramBase::kIPCSerializationSourceFlag);
-
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
- HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
- EXPECT_EQ(histogram, deserialized);
-
- ResetStatisticsRecorder();
-
- PickleIterator iter2(pickle);
- deserialized = DeserializeHistogramInfo(&iter2);
- EXPECT_TRUE(deserialized);
- EXPECT_NE(histogram, deserialized);
- EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
- EXPECT_TRUE(deserialized->HasConstructionArguments(5, 13, 4));
- EXPECT_EQ(0, deserialized->flags());
-}
-
-TEST_F(HistogramBaseTest, DeserializeSparseHistogram) {
- HistogramBase* histogram = SparseHistogram::FactoryGet(
- "TestHistogram", HistogramBase::kIPCSerializationSourceFlag);
-
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
- HistogramBase* deserialized = DeserializeHistogramInfo(&iter);
- EXPECT_EQ(histogram, deserialized);
-
- ResetStatisticsRecorder();
-
- PickleIterator iter2(pickle);
- deserialized = DeserializeHistogramInfo(&iter2);
- EXPECT_TRUE(deserialized);
- EXPECT_NE(histogram, deserialized);
- EXPECT_EQ("TestHistogram", StringPiece(deserialized->histogram_name()));
- EXPECT_EQ(0, deserialized->flags());
-}
-
-TEST_F(HistogramBaseTest, AddKilo) {
- HistogramBase* histogram =
- LinearHistogram::FactoryGet("TestAddKiloHistogram", 1, 1000, 100, 0);
-
- histogram->AddKilo(100, 1000);
- histogram->AddKilo(200, 2000);
- histogram->AddKilo(300, 1500);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
- EXPECT_EQ(1, samples->GetCount(100));
- EXPECT_EQ(2, samples->GetCount(200));
- EXPECT_LE(1, samples->GetCount(300));
- EXPECT_GE(2, samples->GetCount(300));
-}
-
-TEST_F(HistogramBaseTest, AddKiB) {
- HistogramBase* histogram =
- LinearHistogram::FactoryGet("TestAddKiBHistogram", 1, 1000, 100, 0);
-
- histogram->AddKiB(100, 1024);
- histogram->AddKiB(200, 2048);
- histogram->AddKiB(300, 1536);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
- EXPECT_EQ(1, samples->GetCount(100));
- EXPECT_EQ(2, samples->GetCount(200));
- EXPECT_LE(1, samples->GetCount(300));
- EXPECT_GE(2, samples->GetCount(300));
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_delta_serialization_unittest.cc b/base/metrics/histogram_delta_serialization_unittest.cc
deleted file mode 100644
index 719bc70..0000000
--- a/base/metrics/histogram_delta_serialization_unittest.cc
+++ /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.
-
-#include "base/metrics/histogram_delta_serialization.h"
-
-#include <vector>
-
-#include "base/metrics/histogram.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/statistics_recorder.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(HistogramDeltaSerializationTest, DeserializeHistogramAndAddSamples) {
- std::unique_ptr<StatisticsRecorder> statistic_recorder(
- StatisticsRecorder::CreateTemporaryForTesting());
- HistogramDeltaSerialization serializer("HistogramDeltaSerializationTest");
- std::vector<std::string> deltas;
- // Nothing was changed yet.
- serializer.PrepareAndSerializeDeltas(&deltas, true);
- EXPECT_TRUE(deltas.empty());
-
- HistogramBase* histogram = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10, HistogramBase::kIPCSerializationSourceFlag);
- histogram->Add(1);
- histogram->Add(10);
- histogram->Add(100);
- histogram->Add(1000);
-
- serializer.PrepareAndSerializeDeltas(&deltas, true);
- EXPECT_FALSE(deltas.empty());
-
- HistogramDeltaSerialization::DeserializeAndAddSamples(deltas);
-
- // The histogram has kIPCSerializationSourceFlag. So samples will be ignored.
- std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
- EXPECT_EQ(1, snapshot->GetCount(1));
- EXPECT_EQ(1, snapshot->GetCount(10));
- EXPECT_EQ(1, snapshot->GetCount(100));
- EXPECT_EQ(1, snapshot->GetCount(1000));
-
- // Clear kIPCSerializationSourceFlag to emulate multi-process usage.
- histogram->ClearFlags(HistogramBase::kIPCSerializationSourceFlag);
- HistogramDeltaSerialization::DeserializeAndAddSamples(deltas);
-
- std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
- EXPECT_EQ(2, snapshot2->GetCount(1));
- EXPECT_EQ(2, snapshot2->GetCount(10));
- EXPECT_EQ(2, snapshot2->GetCount(100));
- EXPECT_EQ(2, snapshot2->GetCount(1000));
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_functions_unittest.cc b/base/metrics/histogram_functions_unittest.cc
deleted file mode 100644
index 3720674..0000000
--- 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/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_macros_unittest.cc b/base/metrics/histogram_macros_unittest.cc
deleted file mode 100644
index 3c592b0..0000000
--- a/base/metrics/histogram_macros_unittest.cc
+++ /dev/null
@@ -1,57 +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/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(ScopedHistogramTimer, TwoTimersOneScope) {
- SCOPED_UMA_HISTOGRAM_TIMER("TestTimer0");
- SCOPED_UMA_HISTOGRAM_TIMER("TestTimer1");
- SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer0");
- SCOPED_UMA_HISTOGRAM_LONG_TIMER("TestLongTimer1");
-}
-
-// Compile tests for UMA_HISTOGRAM_ENUMERATION with the three different types it
-// accepts:
-// - integral types
-// - unscoped enums
-// - scoped enums
-TEST(HistogramMacro, IntegralPsuedoEnumeration) {
- UMA_HISTOGRAM_ENUMERATION("Test.FauxEnumeration", 1, 10000);
-}
-
-TEST(HistogramMacro, UnscopedEnumeration) {
- enum TestEnum : char {
- FIRST_VALUE,
- SECOND_VALUE,
- THIRD_VALUE,
- MAX_ENTRIES,
- };
- UMA_HISTOGRAM_ENUMERATION("Test.UnscopedEnumeration", SECOND_VALUE,
- MAX_ENTRIES);
-}
-
-TEST(HistogramMacro, ScopedEnumeration) {
- enum class TestEnum {
- FIRST_VALUE,
- SECOND_VALUE,
- THIRD_VALUE,
- kMaxValue = THIRD_VALUE,
- };
- UMA_HISTOGRAM_ENUMERATION("Test.ScopedEnumeration", TestEnum::FIRST_VALUE);
-
- enum class TestEnum2 {
- FIRST_VALUE,
- SECOND_VALUE,
- THIRD_VALUE,
- MAX_ENTRIES,
- };
- UMA_HISTOGRAM_ENUMERATION("Test.ScopedEnumeration2", TestEnum2::SECOND_VALUE,
- TestEnum2::MAX_ENTRIES);
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_samples_unittest.cc b/base/metrics/histogram_samples_unittest.cc
deleted file mode 100644
index 74c743b..0000000
--- a/base/metrics/histogram_samples_unittest.cc
+++ /dev/null
@@ -1,84 +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.
-
-#include "base/metrics/histogram_samples.h"
-
-#include <limits>
-
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-using SingleSample = HistogramSamples::SingleSample;
-using AtomicSingleSample = HistogramSamples::AtomicSingleSample;
-
-TEST(SingleSampleTest, Load) {
- AtomicSingleSample sample;
- ASSERT_TRUE(sample.Accumulate(9, 1));
-
- SingleSample s = sample.Load();
- EXPECT_EQ(9U, s.bucket);
- EXPECT_EQ(1U, s.count);
-
- s = sample.Load();
- EXPECT_EQ(9U, s.bucket);
- EXPECT_EQ(1U, s.count);
-}
-
-TEST(SingleSampleTest, Extract) {
- AtomicSingleSample sample;
- ASSERT_TRUE(sample.Accumulate(9, 1));
-
- SingleSample s = sample.Extract(/*disable=*/false);
- EXPECT_EQ(9U, s.bucket);
- EXPECT_EQ(1U, s.count);
-
- s = sample.Extract(/*disable=*/false);
- EXPECT_EQ(0U, s.bucket);
- EXPECT_EQ(0U, s.count);
-}
-
-TEST(SingleSampleTest, Disable) {
- AtomicSingleSample sample;
- EXPECT_EQ(0U, sample.Extract(/*disable=*/false).count);
- EXPECT_FALSE(sample.IsDisabled());
-
- ASSERT_TRUE(sample.Accumulate(9, 1));
- EXPECT_EQ(1U, sample.Extract(/*disable=*/true).count);
- EXPECT_TRUE(sample.IsDisabled());
-
- ASSERT_FALSE(sample.Accumulate(9, 1));
- EXPECT_EQ(0U, sample.Extract(/*disable=*/false).count);
- EXPECT_FALSE(sample.IsDisabled());
-}
-
-TEST(SingleSampleTest, Accumulate) {
- AtomicSingleSample sample;
-
- ASSERT_TRUE(sample.Accumulate(9, 1));
- ASSERT_TRUE(sample.Accumulate(9, 2));
- ASSERT_TRUE(sample.Accumulate(9, 4));
- EXPECT_EQ(7U, sample.Extract(/*disable=*/false).count);
-
- ASSERT_TRUE(sample.Accumulate(9, 4));
- ASSERT_TRUE(sample.Accumulate(9, -2));
- ASSERT_TRUE(sample.Accumulate(9, 1));
- EXPECT_EQ(3U, sample.Extract(/*disable=*/false).count);
-}
-
-TEST(SingleSampleTest, Overflow) {
- AtomicSingleSample sample;
-
- ASSERT_TRUE(sample.Accumulate(9, 1));
- ASSERT_FALSE(sample.Accumulate(9, -2));
- EXPECT_EQ(1U, sample.Extract(/*disable=*/false).count);
-
- ASSERT_TRUE(sample.Accumulate(9, std::numeric_limits<uint16_t>::max()));
- ASSERT_FALSE(sample.Accumulate(9, 1));
- EXPECT_EQ(std::numeric_limits<uint16_t>::max(),
- sample.Extract(/*disable=*/false).count);
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_snapshot_manager_unittest.cc b/base/metrics/histogram_snapshot_manager_unittest.cc
deleted file mode 100644
index 1e2c599..0000000
--- a/base/metrics/histogram_snapshot_manager_unittest.cc
+++ /dev/null
@@ -1,116 +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/metrics/histogram_snapshot_manager.h"
-
-#include <string>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/metrics/histogram_delta_serialization.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/sample_vector.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/stl_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class HistogramFlattenerDeltaRecorder : public HistogramFlattener {
- public:
- HistogramFlattenerDeltaRecorder() = default;
-
- void RecordDelta(const HistogramBase& histogram,
- const HistogramSamples& snapshot) override {
- recorded_delta_histogram_names_.push_back(histogram.histogram_name());
- // Use CHECK instead of ASSERT to get full stack-trace and thus origin.
- CHECK(!ContainsKey(recorded_delta_histogram_sum_,
- histogram.histogram_name()));
- // Keep pointer to snapshot for testing. This really isn't ideal but the
- // snapshot-manager keeps the snapshot alive until it's "forgotten".
- recorded_delta_histogram_sum_[histogram.histogram_name()] = snapshot.sum();
- }
-
- void Reset() {
- recorded_delta_histogram_names_.clear();
- recorded_delta_histogram_sum_.clear();
- }
-
- std::vector<std::string> GetRecordedDeltaHistogramNames() {
- return recorded_delta_histogram_names_;
- }
-
- int64_t GetRecordedDeltaHistogramSum(const std::string& name) {
- EXPECT_TRUE(ContainsKey(recorded_delta_histogram_sum_, name));
- return recorded_delta_histogram_sum_[name];
- }
-
- private:
- std::vector<std::string> recorded_delta_histogram_names_;
- std::map<std::string, int64_t> recorded_delta_histogram_sum_;
-
- DISALLOW_COPY_AND_ASSIGN(HistogramFlattenerDeltaRecorder);
-};
-
-class HistogramSnapshotManagerTest : public testing::Test {
- protected:
- HistogramSnapshotManagerTest()
- : statistics_recorder_(StatisticsRecorder::CreateTemporaryForTesting()),
- histogram_snapshot_manager_(&histogram_flattener_delta_recorder_) {}
-
- ~HistogramSnapshotManagerTest() override = default;
-
- std::unique_ptr<StatisticsRecorder> statistics_recorder_;
- HistogramFlattenerDeltaRecorder histogram_flattener_delta_recorder_;
- HistogramSnapshotManager histogram_snapshot_manager_;
-};
-
-TEST_F(HistogramSnapshotManagerTest, PrepareDeltasNoFlagsFilter) {
- // kNoFlags filter should record all histograms.
- UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 4);
- UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2);
-
- StatisticsRecorder::PrepareDeltas(false, HistogramBase::kNoFlags,
- HistogramBase::kNoFlags,
- &histogram_snapshot_manager_);
-
- const std::vector<std::string>& histograms =
- histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames();
- EXPECT_EQ(2U, histograms.size());
- EXPECT_EQ("UmaHistogram", histograms[0]);
- EXPECT_EQ("UmaStabilityHistogram", histograms[1]);
-}
-
-TEST_F(HistogramSnapshotManagerTest, PrepareDeltasUmaHistogramFlagFilter) {
- // Note that kUmaStabilityHistogramFlag includes kUmaTargetedHistogramFlag.
- UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 4);
- UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2);
-
- StatisticsRecorder::PrepareDeltas(false, HistogramBase::kNoFlags,
- HistogramBase::kUmaTargetedHistogramFlag,
- &histogram_snapshot_manager_);
-
- const std::vector<std::string>& histograms =
- histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames();
- EXPECT_EQ(2U, histograms.size());
- EXPECT_EQ("UmaHistogram", histograms[0]);
- EXPECT_EQ("UmaStabilityHistogram", histograms[1]);
-}
-
-TEST_F(HistogramSnapshotManagerTest,
- PrepareDeltasUmaStabilityHistogramFlagFilter) {
- UMA_HISTOGRAM_ENUMERATION("UmaHistogram", 1, 4);
- UMA_STABILITY_HISTOGRAM_ENUMERATION("UmaStabilityHistogram", 1, 2);
-
- StatisticsRecorder::PrepareDeltas(false, HistogramBase::kNoFlags,
- HistogramBase::kUmaStabilityHistogramFlag,
- &histogram_snapshot_manager_);
-
- const std::vector<std::string>& histograms =
- histogram_flattener_delta_recorder_.GetRecordedDeltaHistogramNames();
- EXPECT_EQ(1U, histograms.size());
- EXPECT_EQ("UmaStabilityHistogram", histograms[0]);
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_unittest.cc b/base/metrics/histogram_unittest.cc
deleted file mode 100644
index b819393..0000000
--- a/base/metrics/histogram_unittest.cc
+++ /dev/null
@@ -1,841 +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/metrics/histogram.h"
-
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <climits>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include "base/logging.h"
-#include "base/metrics/bucket_ranges.h"
-#include "base/metrics/dummy_histogram.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/metrics_hashes.h"
-#include "base/metrics/persistent_histogram_allocator.h"
-#include "base/metrics/persistent_memory_allocator.h"
-#include "base/metrics/record_histogram_checker.h"
-#include "base/metrics/sample_vector.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/pickle.h"
-#include "base/strings/stringprintf.h"
-#include "base/test/gtest_util.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-const char kExpiredHistogramName[] = "ExpiredHistogram";
-
-// Test implementation of RecordHistogramChecker interface.
-class TestRecordHistogramChecker : public RecordHistogramChecker {
- public:
- ~TestRecordHistogramChecker() override = default;
-
- // RecordHistogramChecker:
- bool ShouldRecord(uint64_t histogram_hash) const override {
- return histogram_hash != HashMetricName(kExpiredHistogramName);
- }
-};
-
-} // namespace
-
-// Test parameter indicates if a persistent memory allocator should be used
-// for histogram allocation. False will allocate histograms from the process
-// heap.
-class HistogramTest : public testing::TestWithParam<bool> {
- protected:
- const int32_t kAllocatorMemorySize = 8 << 20; // 8 MiB
-
- HistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
-
- void SetUp() override {
- if (use_persistent_histogram_allocator_)
- CreatePersistentHistogramAllocator();
-
- // Each test will have a clean state (no Histogram / BucketRanges
- // registered).
- InitializeStatisticsRecorder();
- }
-
- void TearDown() override {
- if (allocator_) {
- ASSERT_FALSE(allocator_->IsFull());
- ASSERT_FALSE(allocator_->IsCorrupt());
- }
- UninitializeStatisticsRecorder();
- DestroyPersistentHistogramAllocator();
- }
-
- void InitializeStatisticsRecorder() {
- DCHECK(!statistics_recorder_);
- statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
- auto record_checker = std::make_unique<TestRecordHistogramChecker>();
- StatisticsRecorder::SetRecordChecker(std::move(record_checker));
- }
-
- void UninitializeStatisticsRecorder() {
- statistics_recorder_.reset();
- }
-
- void CreatePersistentHistogramAllocator() {
- GlobalHistogramAllocator::CreateWithLocalMemory(
- kAllocatorMemorySize, 0, "HistogramAllocatorTest");
- allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
- }
-
- void DestroyPersistentHistogramAllocator() {
- allocator_ = nullptr;
- GlobalHistogramAllocator::ReleaseForTesting();
- }
-
- const bool use_persistent_histogram_allocator_;
-
- std::unique_ptr<StatisticsRecorder> statistics_recorder_;
- std::unique_ptr<char[]> allocator_memory_;
- PersistentMemoryAllocator* allocator_ = nullptr;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HistogramTest);
-};
-
-// Run all HistogramTest cases with both heap and persistent memory.
-INSTANTIATE_TEST_CASE_P(HeapAndPersistent, HistogramTest, testing::Bool());
-
-
-// Check for basic syntax and use.
-TEST_P(HistogramTest, BasicTest) {
- // Try basic construction
- HistogramBase* histogram = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- EXPECT_TRUE(histogram);
-
- HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
- "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- EXPECT_TRUE(linear_histogram);
-
- std::vector<int> custom_ranges;
- custom_ranges.push_back(1);
- custom_ranges.push_back(5);
- HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
- "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
- EXPECT_TRUE(custom_histogram);
-
- // Macros that create histograms have an internal static variable which will
- // continue to point to those from the very first run of this method even
- // during subsequent runs.
- static bool already_run = false;
- if (already_run)
- return;
- already_run = true;
-
- // Use standard macros (but with fixed samples)
- LOCAL_HISTOGRAM_TIMES("Test2Histogram", TimeDelta::FromDays(1));
- LOCAL_HISTOGRAM_COUNTS("Test3Histogram", 30);
-
- LOCAL_HISTOGRAM_ENUMERATION("Test6Histogram", 129, 130);
-}
-
-// Check that the macro correctly matches histograms by name and records their
-// data together.
-TEST_P(HistogramTest, NameMatchTest) {
- // Macros that create histograms have an internal static variable which will
- // continue to point to those from the very first run of this method even
- // during subsequent runs.
- static bool already_run = false;
- if (already_run)
- return;
- already_run = true;
-
- LOCAL_HISTOGRAM_PERCENTAGE("DuplicatedHistogram", 10);
- LOCAL_HISTOGRAM_PERCENTAGE("DuplicatedHistogram", 10);
- HistogramBase* histogram = LinearHistogram::FactoryGet(
- "DuplicatedHistogram", 1, 101, 102, HistogramBase::kNoFlags);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
- EXPECT_EQ(2, samples->TotalCount());
- EXPECT_EQ(2, samples->GetCount(10));
-}
-
-// Check that delta calculations work correctly.
-TEST_P(HistogramTest, DeltaTest) {
- HistogramBase* histogram =
- Histogram::FactoryGet("DeltaHistogram", 1, 64, 8,
- HistogramBase::kNoFlags);
- histogram->Add(1);
- histogram->Add(10);
- histogram->Add(50);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
- EXPECT_EQ(3, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(1));
- EXPECT_EQ(1, samples->GetCount(10));
- EXPECT_EQ(1, samples->GetCount(50));
- EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
-
- samples = histogram->SnapshotDelta();
- EXPECT_EQ(0, samples->TotalCount());
-
- histogram->Add(10);
- histogram->Add(10);
- samples = histogram->SnapshotDelta();
- EXPECT_EQ(2, samples->TotalCount());
- EXPECT_EQ(2, samples->GetCount(10));
-
- samples = histogram->SnapshotDelta();
- EXPECT_EQ(0, samples->TotalCount());
-}
-
-// Check that final-delta calculations work correctly.
-TEST_P(HistogramTest, FinalDeltaTest) {
- HistogramBase* histogram =
- Histogram::FactoryGet("FinalDeltaHistogram", 1, 64, 8,
- HistogramBase::kNoFlags);
- histogram->Add(1);
- histogram->Add(10);
- histogram->Add(50);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
- EXPECT_EQ(3, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(1));
- EXPECT_EQ(1, samples->GetCount(10));
- EXPECT_EQ(1, samples->GetCount(50));
- EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
-
- histogram->Add(2);
- histogram->Add(50);
-
- samples = histogram->SnapshotFinalDelta();
- EXPECT_EQ(2, samples->TotalCount());
- EXPECT_EQ(1, samples->GetCount(2));
- EXPECT_EQ(1, samples->GetCount(50));
- EXPECT_EQ(samples->TotalCount(), samples->redundant_count());
-}
-
-TEST_P(HistogramTest, ExponentialRangesTest) {
- // Check that we got a nice exponential when there was enough room.
- BucketRanges ranges(9);
- Histogram::InitializeBucketRanges(1, 64, &ranges);
- EXPECT_EQ(0, ranges.range(0));
- int power_of_2 = 1;
- for (int i = 1; i < 8; i++) {
- EXPECT_EQ(power_of_2, ranges.range(i));
- power_of_2 *= 2;
- }
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges.range(8));
-
- // Check the corresponding Histogram will use the correct ranges.
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
- EXPECT_TRUE(ranges.Equals(histogram->bucket_ranges()));
-
- // When bucket count is limited, exponential ranges will partially look like
- // linear.
- BucketRanges ranges2(16);
- Histogram::InitializeBucketRanges(1, 32, &ranges2);
-
- EXPECT_EQ(0, ranges2.range(0));
- EXPECT_EQ(1, ranges2.range(1));
- EXPECT_EQ(2, ranges2.range(2));
- EXPECT_EQ(3, ranges2.range(3));
- EXPECT_EQ(4, ranges2.range(4));
- EXPECT_EQ(5, ranges2.range(5));
- EXPECT_EQ(6, ranges2.range(6));
- EXPECT_EQ(7, ranges2.range(7));
- EXPECT_EQ(9, ranges2.range(8));
- EXPECT_EQ(11, ranges2.range(9));
- EXPECT_EQ(14, ranges2.range(10));
- EXPECT_EQ(17, ranges2.range(11));
- EXPECT_EQ(21, ranges2.range(12));
- EXPECT_EQ(26, ranges2.range(13));
- EXPECT_EQ(32, ranges2.range(14));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges2.range(15));
-
- // Check the corresponding Histogram will use the correct ranges.
- Histogram* histogram2 = static_cast<Histogram*>(
- Histogram::FactoryGet("Histogram2", 1, 32, 15, HistogramBase::kNoFlags));
- EXPECT_TRUE(ranges2.Equals(histogram2->bucket_ranges()));
-}
-
-TEST_P(HistogramTest, LinearRangesTest) {
- BucketRanges ranges(9);
- LinearHistogram::InitializeBucketRanges(1, 7, &ranges);
- // Gets a nice linear set of bucket ranges.
- for (int i = 0; i < 8; i++)
- EXPECT_EQ(i, ranges.range(i));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges.range(8));
-
- // The correspoding LinearHistogram should use the correct ranges.
- Histogram* histogram = static_cast<Histogram*>(
- LinearHistogram::FactoryGet("Linear", 1, 7, 8, HistogramBase::kNoFlags));
- EXPECT_TRUE(ranges.Equals(histogram->bucket_ranges()));
-
- // Linear ranges are not divisible.
- BucketRanges ranges2(6);
- LinearHistogram::InitializeBucketRanges(1, 6, &ranges2);
- EXPECT_EQ(0, ranges2.range(0));
- EXPECT_EQ(1, ranges2.range(1));
- EXPECT_EQ(3, ranges2.range(2));
- EXPECT_EQ(4, ranges2.range(3));
- EXPECT_EQ(6, ranges2.range(4));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges2.range(5));
- // The correspoding LinearHistogram should use the correct ranges.
- Histogram* histogram2 = static_cast<Histogram*>(
- LinearHistogram::FactoryGet("Linear2", 1, 6, 5, HistogramBase::kNoFlags));
- EXPECT_TRUE(ranges2.Equals(histogram2->bucket_ranges()));
-}
-
-TEST_P(HistogramTest, ArrayToCustomEnumRangesTest) {
- const HistogramBase::Sample ranges[3] = {5, 10, 20};
- std::vector<HistogramBase::Sample> ranges_vec =
- CustomHistogram::ArrayToCustomEnumRanges(ranges);
- ASSERT_EQ(6u, ranges_vec.size());
- EXPECT_EQ(5, ranges_vec[0]);
- EXPECT_EQ(6, ranges_vec[1]);
- EXPECT_EQ(10, ranges_vec[2]);
- EXPECT_EQ(11, ranges_vec[3]);
- EXPECT_EQ(20, ranges_vec[4]);
- EXPECT_EQ(21, ranges_vec[5]);
-}
-
-TEST_P(HistogramTest, CustomHistogramTest) {
- // A well prepared custom ranges.
- std::vector<HistogramBase::Sample> custom_ranges;
- custom_ranges.push_back(1);
- custom_ranges.push_back(2);
-
- Histogram* histogram = static_cast<Histogram*>(
- CustomHistogram::FactoryGet("TestCustomHistogram1", custom_ranges,
- HistogramBase::kNoFlags));
- const BucketRanges* ranges = histogram->bucket_ranges();
- ASSERT_EQ(4u, ranges->size());
- EXPECT_EQ(0, ranges->range(0)); // Auto added.
- EXPECT_EQ(1, ranges->range(1));
- EXPECT_EQ(2, ranges->range(2));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3)); // Auto added.
-
- // A unordered custom ranges.
- custom_ranges.clear();
- custom_ranges.push_back(2);
- custom_ranges.push_back(1);
- histogram = static_cast<Histogram*>(
- CustomHistogram::FactoryGet("TestCustomHistogram2", custom_ranges,
- HistogramBase::kNoFlags));
- ranges = histogram->bucket_ranges();
- ASSERT_EQ(4u, ranges->size());
- EXPECT_EQ(0, ranges->range(0));
- EXPECT_EQ(1, ranges->range(1));
- EXPECT_EQ(2, ranges->range(2));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));
-
- // A custom ranges with duplicated values.
- custom_ranges.clear();
- custom_ranges.push_back(4);
- custom_ranges.push_back(1);
- custom_ranges.push_back(4);
- histogram = static_cast<Histogram*>(
- CustomHistogram::FactoryGet("TestCustomHistogram3", custom_ranges,
- HistogramBase::kNoFlags));
- ranges = histogram->bucket_ranges();
- ASSERT_EQ(4u, ranges->size());
- EXPECT_EQ(0, ranges->range(0));
- EXPECT_EQ(1, ranges->range(1));
- EXPECT_EQ(4, ranges->range(2));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(3));
-}
-
-TEST_P(HistogramTest, CustomHistogramWithOnly2Buckets) {
- // This test exploits the fact that the CustomHistogram can have 2 buckets,
- // while the base class Histogram is *supposed* to have at least 3 buckets.
- // We should probably change the restriction on the base class (or not inherit
- // the base class!).
-
- std::vector<HistogramBase::Sample> custom_ranges;
- custom_ranges.push_back(4);
-
- Histogram* histogram = static_cast<Histogram*>(
- CustomHistogram::FactoryGet("2BucketsCustomHistogram", custom_ranges,
- HistogramBase::kNoFlags));
- const BucketRanges* ranges = histogram->bucket_ranges();
- ASSERT_EQ(3u, ranges->size());
- EXPECT_EQ(0, ranges->range(0));
- EXPECT_EQ(4, ranges->range(1));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(2));
-}
-
-TEST_P(HistogramTest, AddCountTest) {
- const size_t kBucketCount = 50;
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("AddCountHistogram", 10, 100, kBucketCount,
- HistogramBase::kNoFlags));
-
- histogram->AddCount(20, 15);
- histogram->AddCount(30, 14);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
- EXPECT_EQ(29, samples->TotalCount());
- EXPECT_EQ(15, samples->GetCount(20));
- EXPECT_EQ(14, samples->GetCount(30));
-
- histogram->AddCount(20, 25);
- histogram->AddCount(30, 24);
-
- std::unique_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
- EXPECT_EQ(78, samples2->TotalCount());
- EXPECT_EQ(40, samples2->GetCount(20));
- EXPECT_EQ(38, samples2->GetCount(30));
-}
-
-TEST_P(HistogramTest, AddCount_LargeValuesDontOverflow) {
- const size_t kBucketCount = 50;
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("AddCountHistogram", 10, 1000000000, kBucketCount,
- HistogramBase::kNoFlags));
-
- histogram->AddCount(200000000, 15);
- histogram->AddCount(300000000, 14);
-
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotSamples();
- EXPECT_EQ(29, samples->TotalCount());
- EXPECT_EQ(15, samples->GetCount(200000000));
- EXPECT_EQ(14, samples->GetCount(300000000));
-
- histogram->AddCount(200000000, 25);
- histogram->AddCount(300000000, 24);
-
- std::unique_ptr<HistogramSamples> samples2 = histogram->SnapshotSamples();
- EXPECT_EQ(78, samples2->TotalCount());
- EXPECT_EQ(40, samples2->GetCount(200000000));
- EXPECT_EQ(38, samples2->GetCount(300000000));
- EXPECT_EQ(19400000000LL, samples2->sum());
-}
-
-// Some metrics are designed so that they are guaranteed not to overflow between
-// snapshots, but could overflow over a long-running session.
-// Make sure that counts returned by Histogram::SnapshotDelta do not overflow
-// even when a total count (returned by Histogram::SnapshotSample) does.
-TEST_P(HistogramTest, AddCount_LargeCountsDontOverflow) {
- const size_t kBucketCount = 10;
- Histogram* histogram = static_cast<Histogram*>(Histogram::FactoryGet(
- "AddCountHistogram", 10, 50, kBucketCount, HistogramBase::kNoFlags));
-
- const int count = (1 << 30) - 1;
-
- // Repeat N times to make sure that there is no internal value overflow.
- for (int i = 0; i < 10; ++i) {
- histogram->AddCount(42, count);
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
- EXPECT_EQ(count, samples->TotalCount());
- EXPECT_EQ(count, samples->GetCount(42));
- }
-}
-
-// Make sure histogram handles out-of-bounds data gracefully.
-TEST_P(HistogramTest, BoundsTest) {
- const size_t kBucketCount = 50;
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("Bounded", 10, 100, kBucketCount,
- HistogramBase::kNoFlags));
-
- // Put two samples "out of bounds" above and below.
- histogram->Add(5);
- histogram->Add(-50);
-
- histogram->Add(100);
- histogram->Add(10000);
-
- // Verify they landed in the underflow, and overflow buckets.
- std::unique_ptr<SampleVector> samples = histogram->SnapshotAllSamples();
- EXPECT_EQ(2, samples->GetCountAtIndex(0));
- EXPECT_EQ(0, samples->GetCountAtIndex(1));
- size_t array_size = histogram->bucket_count();
- EXPECT_EQ(kBucketCount, array_size);
- EXPECT_EQ(0, samples->GetCountAtIndex(array_size - 2));
- EXPECT_EQ(2, samples->GetCountAtIndex(array_size - 1));
-
- std::vector<int> custom_ranges;
- custom_ranges.push_back(10);
- custom_ranges.push_back(50);
- custom_ranges.push_back(100);
- Histogram* test_custom_histogram = static_cast<Histogram*>(
- CustomHistogram::FactoryGet("TestCustomRangeBoundedHistogram",
- custom_ranges, HistogramBase::kNoFlags));
-
- // Put two samples "out of bounds" above and below.
- test_custom_histogram->Add(5);
- test_custom_histogram->Add(-50);
- test_custom_histogram->Add(100);
- test_custom_histogram->Add(1000);
- test_custom_histogram->Add(INT_MAX);
-
- // Verify they landed in the underflow, and overflow buckets.
- std::unique_ptr<SampleVector> custom_samples =
- test_custom_histogram->SnapshotAllSamples();
- EXPECT_EQ(2, custom_samples->GetCountAtIndex(0));
- EXPECT_EQ(0, custom_samples->GetCountAtIndex(1));
- size_t bucket_count = test_custom_histogram->bucket_count();
- EXPECT_EQ(0, custom_samples->GetCountAtIndex(bucket_count - 2));
- EXPECT_EQ(3, custom_samples->GetCountAtIndex(bucket_count - 1));
-}
-
-// Check to be sure samples land as expected is "correct" buckets.
-TEST_P(HistogramTest, BucketPlacementTest) {
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
-
- // Add i+1 samples to the i'th bucket.
- histogram->Add(0);
- int power_of_2 = 1;
- for (int i = 1; i < 8; i++) {
- for (int j = 0; j <= i; j++)
- histogram->Add(power_of_2);
- power_of_2 *= 2;
- }
-
- // Check to see that the bucket counts reflect our additions.
- std::unique_ptr<SampleVector> samples = histogram->SnapshotAllSamples();
- for (int i = 0; i < 8; i++)
- EXPECT_EQ(i + 1, samples->GetCountAtIndex(i));
-}
-
-TEST_P(HistogramTest, CorruptSampleCounts) {
- // The internal code creates histograms via macros and thus keeps static
- // pointers to them. If those pointers are to persistent memory which will
- // be free'd then any following calls to that code will crash with a
- // segmentation violation.
- if (use_persistent_histogram_allocator_)
- return;
-
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
-
- // Add some samples.
- histogram->Add(20);
- histogram->Add(40);
-
- std::unique_ptr<SampleVector> snapshot = histogram->SnapshotAllSamples();
- EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
- histogram->FindCorruption(*snapshot));
- EXPECT_EQ(2, snapshot->redundant_count());
- EXPECT_EQ(2, snapshot->TotalCount());
-
- snapshot->counts()[3] += 100; // Sample count won't match redundant count.
- EXPECT_EQ(HistogramBase::COUNT_LOW_ERROR,
- histogram->FindCorruption(*snapshot));
- snapshot->counts()[2] -= 200;
- EXPECT_EQ(HistogramBase::COUNT_HIGH_ERROR,
- histogram->FindCorruption(*snapshot));
-
- // But we can't spot a corruption if it is compensated for.
- snapshot->counts()[1] += 100;
- EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
- histogram->FindCorruption(*snapshot));
-}
-
-TEST_P(HistogramTest, CorruptBucketBounds) {
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags));
-
- std::unique_ptr<HistogramSamples> snapshot = histogram->SnapshotSamples();
- EXPECT_EQ(HistogramBase::NO_INCONSISTENCIES,
- histogram->FindCorruption(*snapshot));
-
- BucketRanges* bucket_ranges =
- const_cast<BucketRanges*>(histogram->bucket_ranges());
- HistogramBase::Sample tmp = bucket_ranges->range(1);
- bucket_ranges->set_range(1, bucket_ranges->range(2));
- bucket_ranges->set_range(2, tmp);
- EXPECT_EQ(
- HistogramBase::BUCKET_ORDER_ERROR | HistogramBase::RANGE_CHECKSUM_ERROR,
- histogram->FindCorruption(*snapshot));
-
- bucket_ranges->set_range(2, bucket_ranges->range(1));
- bucket_ranges->set_range(1, tmp);
- EXPECT_EQ(0U, histogram->FindCorruption(*snapshot));
-
- // Show that two simple changes don't offset each other
- bucket_ranges->set_range(3, bucket_ranges->range(3) + 1);
- EXPECT_EQ(HistogramBase::RANGE_CHECKSUM_ERROR,
- histogram->FindCorruption(*snapshot));
-
- bucket_ranges->set_range(4, bucket_ranges->range(4) - 1);
- EXPECT_EQ(HistogramBase::RANGE_CHECKSUM_ERROR,
- histogram->FindCorruption(*snapshot));
-
- // Repair histogram so that destructor won't DCHECK().
- bucket_ranges->set_range(3, bucket_ranges->range(3) - 1);
- bucket_ranges->set_range(4, bucket_ranges->range(4) + 1);
-}
-
-TEST_P(HistogramTest, HistogramSerializeInfo) {
- Histogram* histogram = static_cast<Histogram*>(
- Histogram::FactoryGet("Histogram", 1, 64, 8,
- HistogramBase::kIPCSerializationSourceFlag));
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
-
- int type;
- EXPECT_TRUE(iter.ReadInt(&type));
- EXPECT_EQ(HISTOGRAM, type);
-
- std::string name;
- EXPECT_TRUE(iter.ReadString(&name));
- EXPECT_EQ("Histogram", name);
-
- int flag;
- EXPECT_TRUE(iter.ReadInt(&flag));
- EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag,
- flag & ~HistogramBase::kIsPersistent);
-
- int min;
- EXPECT_TRUE(iter.ReadInt(&min));
- EXPECT_EQ(1, min);
-
- int max;
- EXPECT_TRUE(iter.ReadInt(&max));
- EXPECT_EQ(64, max);
-
- uint32_t bucket_count;
- EXPECT_TRUE(iter.ReadUInt32(&bucket_count));
- EXPECT_EQ(8u, bucket_count);
-
- uint32_t checksum;
- EXPECT_TRUE(iter.ReadUInt32(&checksum));
- EXPECT_EQ(histogram->bucket_ranges()->checksum(), checksum);
-
- // No more data in the pickle.
- EXPECT_FALSE(iter.SkipBytes(1));
-}
-
-TEST_P(HistogramTest, CustomHistogramSerializeInfo) {
- std::vector<int> custom_ranges;
- custom_ranges.push_back(10);
- custom_ranges.push_back(100);
-
- HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
- "TestCustomRangeBoundedHistogram",
- custom_ranges,
- HistogramBase::kNoFlags);
- Pickle pickle;
- custom_histogram->SerializeInfo(&pickle);
-
- // Validate the pickle.
- PickleIterator iter(pickle);
-
- int i;
- std::string s;
- uint32_t bucket_count;
- uint32_t ui32;
- EXPECT_TRUE(iter.ReadInt(&i) && iter.ReadString(&s) && iter.ReadInt(&i) &&
- iter.ReadInt(&i) && iter.ReadInt(&i) &&
- iter.ReadUInt32(&bucket_count) && iter.ReadUInt32(&ui32));
- EXPECT_EQ(3u, bucket_count);
-
- int range;
- EXPECT_TRUE(iter.ReadInt(&range));
- EXPECT_EQ(10, range);
- EXPECT_TRUE(iter.ReadInt(&range));
- EXPECT_EQ(100, range);
-
- // No more data in the pickle.
- EXPECT_FALSE(iter.SkipBytes(1));
-}
-
-TEST_P(HistogramTest, BadConstruction) {
- HistogramBase* histogram = Histogram::FactoryGet(
- "BadConstruction", 0, 100, 8, HistogramBase::kNoFlags);
- EXPECT_TRUE(histogram->HasConstructionArguments(1, 100, 8));
-
- // Try to get the same histogram name with different arguments.
- HistogramBase* bad_histogram = Histogram::FactoryGet(
- "BadConstruction", 0, 100, 7, HistogramBase::kNoFlags);
- EXPECT_EQ(DummyHistogram::GetInstance(), bad_histogram);
- bad_histogram = Histogram::FactoryGet(
- "BadConstruction", 0, 99, 8, HistogramBase::kNoFlags);
- EXPECT_EQ(DummyHistogram::GetInstance(), bad_histogram);
-
- HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
- "BadConstructionLinear", 0, 100, 8, HistogramBase::kNoFlags);
- EXPECT_TRUE(linear_histogram->HasConstructionArguments(1, 100, 8));
-
- // Try to get the same histogram name with different arguments.
- bad_histogram = LinearHistogram::FactoryGet(
- "BadConstructionLinear", 0, 100, 7, HistogramBase::kNoFlags);
- EXPECT_EQ(DummyHistogram::GetInstance(), bad_histogram);
- bad_histogram = LinearHistogram::FactoryGet(
- "BadConstructionLinear", 10, 100, 8, HistogramBase::kNoFlags);
- EXPECT_EQ(DummyHistogram::GetInstance(), bad_histogram);
-}
-
-TEST_P(HistogramTest, FactoryTime) {
- const int kTestCreateCount = 1 << 14; // Must be power-of-2.
- const int kTestLookupCount = 100000;
- const int kTestAddCount = 1000000;
-
- // Create all histogram names in advance for accurate timing below.
- std::vector<std::string> histogram_names;
- for (int i = 0; i < kTestCreateCount; ++i) {
- histogram_names.push_back(
- StringPrintf("TestHistogram.%d", i % kTestCreateCount));
- }
-
- // Calculate cost of creating histograms.
- TimeTicks create_start = TimeTicks::Now();
- for (int i = 0; i < kTestCreateCount; ++i) {
- Histogram::FactoryGet(histogram_names[i], 1, 100, 10,
- HistogramBase::kNoFlags);
- }
- TimeDelta create_ticks = TimeTicks::Now() - create_start;
- int64_t create_ms = create_ticks.InMilliseconds();
-
- VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
- << "ms or about "
- << (create_ms * 1000000) / kTestCreateCount
- << "ns each.";
-
- // Calculate cost of looking up existing histograms.
- TimeTicks lookup_start = TimeTicks::Now();
- for (int i = 0; i < kTestLookupCount; ++i) {
- // 6007 is co-prime with kTestCreateCount and so will do lookups in an
- // order less likely to be cacheable (but still hit them all) should the
- // underlying storage use the exact histogram name as the key.
- const int i_mult = 6007;
- static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
- int index = (i * i_mult) & (kTestCreateCount - 1);
- Histogram::FactoryGet(histogram_names[index], 1, 100, 10,
- HistogramBase::kNoFlags);
- }
- TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
- int64_t lookup_ms = lookup_ticks.InMilliseconds();
-
- VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
- << "ms or about "
- << (lookup_ms * 1000000) / kTestLookupCount
- << "ns each.";
-
- // Calculate cost of accessing histograms.
- HistogramBase* histogram = Histogram::FactoryGet(
- histogram_names[0], 1, 100, 10, HistogramBase::kNoFlags);
- ASSERT_TRUE(histogram);
- TimeTicks add_start = TimeTicks::Now();
- for (int i = 0; i < kTestAddCount; ++i)
- histogram->Add(i & 127);
- TimeDelta add_ticks = TimeTicks::Now() - add_start;
- int64_t add_ms = add_ticks.InMilliseconds();
-
- VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
- << "ms or about "
- << (add_ms * 1000000) / kTestAddCount
- << "ns each.";
-}
-
-// For Histogram, LinearHistogram and CustomHistogram, the minimum for a
-// declared range is 1, while the maximum is (HistogramBase::kSampleType_MAX -
-// 1). But we accept ranges exceeding those limits, and silently clamped to
-// those limits. This is for backwards compatibility.
-TEST(HistogramDeathTest, BadRangesTest) {
- HistogramBase* histogram = Histogram::FactoryGet(
- "BadRanges", 0, HistogramBase::kSampleType_MAX, 8,
- HistogramBase::kNoFlags);
- EXPECT_TRUE(
- histogram->HasConstructionArguments(
- 1, HistogramBase::kSampleType_MAX - 1, 8));
-
- HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
- "BadRangesLinear", 0, HistogramBase::kSampleType_MAX, 8,
- HistogramBase::kNoFlags);
- EXPECT_TRUE(
- linear_histogram->HasConstructionArguments(
- 1, HistogramBase::kSampleType_MAX - 1, 8));
-
- std::vector<int> custom_ranges;
- custom_ranges.push_back(0);
- custom_ranges.push_back(5);
- Histogram* custom_histogram = static_cast<Histogram*>(
- CustomHistogram::FactoryGet(
- "BadRangesCustom", custom_ranges, HistogramBase::kNoFlags));
- const BucketRanges* ranges = custom_histogram->bucket_ranges();
- ASSERT_EQ(3u, ranges->size());
- EXPECT_EQ(0, ranges->range(0));
- EXPECT_EQ(5, ranges->range(1));
- EXPECT_EQ(HistogramBase::kSampleType_MAX, ranges->range(2));
-
- // CustomHistogram does not accepts kSampleType_MAX as range.
- custom_ranges.push_back(HistogramBase::kSampleType_MAX);
- EXPECT_DEATH_IF_SUPPORTED(
- CustomHistogram::FactoryGet("BadRangesCustom2", custom_ranges,
- HistogramBase::kNoFlags),
- "");
-
- // CustomHistogram needs at least 1 valid range.
- custom_ranges.clear();
- custom_ranges.push_back(0);
- EXPECT_DEATH_IF_SUPPORTED(
- CustomHistogram::FactoryGet("BadRangesCustom3", custom_ranges,
- HistogramBase::kNoFlags),
- "");
-}
-
-TEST_P(HistogramTest, ExpiredHistogramTest) {
- HistogramBase* expired = Histogram::FactoryGet(kExpiredHistogramName, 1, 1000,
- 10, HistogramBase::kNoFlags);
- ASSERT_TRUE(expired);
- expired->Add(5);
- expired->Add(500);
- auto samples = expired->SnapshotDelta();
- EXPECT_EQ(0, samples->TotalCount());
-
- HistogramBase* linear_expired = LinearHistogram::FactoryGet(
- kExpiredHistogramName, 1, 1000, 10, HistogramBase::kNoFlags);
- ASSERT_TRUE(linear_expired);
- linear_expired->Add(5);
- linear_expired->Add(500);
- samples = linear_expired->SnapshotDelta();
- EXPECT_EQ(0, samples->TotalCount());
-
- std::vector<int> custom_ranges;
- custom_ranges.push_back(1);
- custom_ranges.push_back(5);
- HistogramBase* custom_expired = CustomHistogram::FactoryGet(
- kExpiredHistogramName, custom_ranges, HistogramBase::kNoFlags);
- ASSERT_TRUE(custom_expired);
- custom_expired->Add(2);
- custom_expired->Add(4);
- samples = custom_expired->SnapshotDelta();
- EXPECT_EQ(0, samples->TotalCount());
-
- HistogramBase* valid = Histogram::FactoryGet("ValidHistogram", 1, 1000, 10,
- HistogramBase::kNoFlags);
- ASSERT_TRUE(valid);
- valid->Add(5);
- valid->Add(500);
- samples = valid->SnapshotDelta();
- EXPECT_EQ(2, samples->TotalCount());
-
- HistogramBase* linear_valid = LinearHistogram::FactoryGet(
- "LinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- ASSERT_TRUE(linear_valid);
- linear_valid->Add(5);
- linear_valid->Add(500);
- samples = linear_valid->SnapshotDelta();
- EXPECT_EQ(2, samples->TotalCount());
-
- HistogramBase* custom_valid = CustomHistogram::FactoryGet(
- "CustomHistogram", custom_ranges, HistogramBase::kNoFlags);
- ASSERT_TRUE(custom_valid);
- custom_valid->Add(2);
- custom_valid->Add(4);
- samples = custom_valid->SnapshotDelta();
- EXPECT_EQ(2, samples->TotalCount());
-}
-
-} // namespace base
diff --git a/base/metrics/histogram_unittest.nc b/base/metrics/histogram_unittest.nc
deleted file mode 100644
index c9c2657..0000000
--- 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/metrics/metrics_hashes_unittest.cc b/base/metrics/metrics_hashes_unittest.cc
deleted file mode 100644
index aea254e..0000000
--- a/base/metrics/metrics_hashes_unittest.cc
+++ /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.
-
-#include "base/metrics/metrics_hashes.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/format_macros.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// Make sure our ID hashes are the same as what we see on the server side.
-TEST(MetricsUtilTest, HashMetricName) {
- static const struct {
- std::string input;
- std::string output;
- } cases[] = {
- {"Back", "0x0557fa923dcee4d0"},
- {"Forward", "0x67d2f6740a8eaebf"},
- {"NewTab", "0x290eb683f96572f1"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- uint64_t hash = HashMetricName(cases[i].input);
- std::string hash_hex = base::StringPrintf("0x%016" PRIx64, hash);
- EXPECT_EQ(cases[i].output, hash_hex);
- }
-}
-
-} // namespace metrics
diff --git a/base/metrics/persistent_histogram_allocator_unittest.cc b/base/metrics/persistent_histogram_allocator_unittest.cc
deleted file mode 100644
index 7e07386..0000000
--- a/base/metrics/persistent_histogram_allocator_unittest.cc
+++ /dev/null
@@ -1,375 +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/persistent_histogram_allocator.h"
-
-#include "base/files/file.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/memory/ptr_util.h"
-#include "base/metrics/bucket_ranges.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/persistent_memory_allocator.h"
-#include "base/metrics/statistics_recorder.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-class PersistentHistogramAllocatorTest : public testing::Test {
- protected:
- const int32_t kAllocatorMemorySize = 64 << 10; // 64 KiB
-
- PersistentHistogramAllocatorTest()
- : statistics_recorder_(StatisticsRecorder::CreateTemporaryForTesting()) {
- CreatePersistentHistogramAllocator();
- }
- ~PersistentHistogramAllocatorTest() override {
- DestroyPersistentHistogramAllocator();
- }
-
- void CreatePersistentHistogramAllocator() {
- allocator_memory_.reset(new char[kAllocatorMemorySize]);
-
- GlobalHistogramAllocator::ReleaseForTesting();
- memset(allocator_memory_.get(), 0, kAllocatorMemorySize);
- GlobalHistogramAllocator::CreateWithPersistentMemory(
- allocator_memory_.get(), kAllocatorMemorySize, 0, 0,
- "PersistentHistogramAllocatorTest");
- allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
- }
-
- void DestroyPersistentHistogramAllocator() {
- allocator_ = nullptr;
- GlobalHistogramAllocator::ReleaseForTesting();
- }
-
- std::unique_ptr<StatisticsRecorder> statistics_recorder_;
- std::unique_ptr<char[]> allocator_memory_;
- PersistentMemoryAllocator* allocator_ = nullptr;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(PersistentHistogramAllocatorTest);
-};
-
-TEST_F(PersistentHistogramAllocatorTest, CreateAndIterate) {
- PersistentMemoryAllocator::MemoryInfo meminfo0;
- allocator_->GetMemoryInfo(&meminfo0);
-
- // Try basic construction
- HistogramBase* histogram = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10, HistogramBase::kIsPersistent);
- EXPECT_TRUE(histogram);
- histogram->CheckName("TestHistogram");
- PersistentMemoryAllocator::MemoryInfo meminfo1;
- allocator_->GetMemoryInfo(&meminfo1);
- EXPECT_GT(meminfo0.free, meminfo1.free);
-
- HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
- "TestLinearHistogram", 1, 1000, 10, HistogramBase::kIsPersistent);
- EXPECT_TRUE(linear_histogram);
- linear_histogram->CheckName("TestLinearHistogram");
- PersistentMemoryAllocator::MemoryInfo meminfo2;
- allocator_->GetMemoryInfo(&meminfo2);
- EXPECT_GT(meminfo1.free, meminfo2.free);
-
- HistogramBase* boolean_histogram = BooleanHistogram::FactoryGet(
- "TestBooleanHistogram", HistogramBase::kIsPersistent);
- EXPECT_TRUE(boolean_histogram);
- boolean_histogram->CheckName("TestBooleanHistogram");
- PersistentMemoryAllocator::MemoryInfo meminfo3;
- allocator_->GetMemoryInfo(&meminfo3);
- EXPECT_GT(meminfo2.free, meminfo3.free);
-
- std::vector<int> custom_ranges;
- custom_ranges.push_back(1);
- custom_ranges.push_back(5);
- HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
- "TestCustomHistogram", custom_ranges, HistogramBase::kIsPersistent);
- EXPECT_TRUE(custom_histogram);
- custom_histogram->CheckName("TestCustomHistogram");
- PersistentMemoryAllocator::MemoryInfo meminfo4;
- allocator_->GetMemoryInfo(&meminfo4);
- EXPECT_GT(meminfo3.free, meminfo4.free);
-
- PersistentMemoryAllocator::Iterator iter(allocator_);
- uint32_t type;
- EXPECT_NE(0U, iter.GetNext(&type)); // Histogram
- EXPECT_NE(0U, iter.GetNext(&type)); // LinearHistogram
- EXPECT_NE(0U, iter.GetNext(&type)); // BooleanHistogram
- EXPECT_NE(0U, iter.GetNext(&type)); // CustomHistogram
- EXPECT_EQ(0U, iter.GetNext(&type));
-
- // Create a second allocator and have it access the memory of the first.
- std::unique_ptr<HistogramBase> recovered;
- PersistentHistogramAllocator recovery(
- std::make_unique<PersistentMemoryAllocator>(
- allocator_memory_.get(), kAllocatorMemorySize, 0, 0, "", false));
- PersistentHistogramAllocator::Iterator histogram_iter(&recovery);
-
- recovered = histogram_iter.GetNext();
- ASSERT_TRUE(recovered);
- recovered->CheckName("TestHistogram");
-
- recovered = histogram_iter.GetNext();
- ASSERT_TRUE(recovered);
- recovered->CheckName("TestLinearHistogram");
-
- recovered = histogram_iter.GetNext();
- ASSERT_TRUE(recovered);
- recovered->CheckName("TestBooleanHistogram");
-
- recovered = histogram_iter.GetNext();
- ASSERT_TRUE(recovered);
- recovered->CheckName("TestCustomHistogram");
-
- recovered = histogram_iter.GetNext();
- EXPECT_FALSE(recovered);
-}
-
-TEST_F(PersistentHistogramAllocatorTest, ConstructPaths) {
- const FilePath dir_path(FILE_PATH_LITERAL("foo/"));
- const std::string dir_string =
- dir_path.NormalizePathSeparators().AsUTF8Unsafe();
-
- FilePath path = GlobalHistogramAllocator::ConstructFilePath(dir_path, "bar");
- EXPECT_EQ(dir_string + "bar.pma", path.AsUTF8Unsafe());
-
- std::string name;
- Time stamp;
- ProcessId pid;
- EXPECT_FALSE(
- GlobalHistogramAllocator::ParseFilePath(path, &name, nullptr, nullptr));
- EXPECT_FALSE(
- GlobalHistogramAllocator::ParseFilePath(path, nullptr, &stamp, nullptr));
- EXPECT_FALSE(
- GlobalHistogramAllocator::ParseFilePath(path, nullptr, nullptr, &pid));
-
- path = GlobalHistogramAllocator::ConstructFilePathForUploadDir(
- dir_path, "bar", Time::FromTimeT(12345), 6789);
- EXPECT_EQ(dir_string + "bar-3039-1A85.pma", path.AsUTF8Unsafe());
- ASSERT_TRUE(
- GlobalHistogramAllocator::ParseFilePath(path, &name, &stamp, &pid));
- EXPECT_EQ(name, "bar");
- EXPECT_EQ(Time::FromTimeT(12345), stamp);
- EXPECT_EQ(static_cast<ProcessId>(6789), pid);
-}
-
-TEST_F(PersistentHistogramAllocatorTest, CreateWithFile) {
- const char temp_name[] = "CreateWithFileTest";
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath temp_file = temp_dir.GetPath().AppendASCII(temp_name);
- const size_t temp_size = 64 << 10; // 64 KiB
-
- // Test creation of a new file.
- GlobalHistogramAllocator::ReleaseForTesting();
- GlobalHistogramAllocator::CreateWithFile(temp_file, temp_size, 0, temp_name);
- EXPECT_EQ(std::string(temp_name),
- GlobalHistogramAllocator::Get()->memory_allocator()->Name());
-
- // Test re-open of a possibly-existing file.
- GlobalHistogramAllocator::ReleaseForTesting();
- GlobalHistogramAllocator::CreateWithFile(temp_file, temp_size, 0, "");
- EXPECT_EQ(std::string(temp_name),
- GlobalHistogramAllocator::Get()->memory_allocator()->Name());
-
- // Test re-open of an known-existing file.
- GlobalHistogramAllocator::ReleaseForTesting();
- GlobalHistogramAllocator::CreateWithFile(temp_file, 0, 0, "");
- EXPECT_EQ(std::string(temp_name),
- GlobalHistogramAllocator::Get()->memory_allocator()->Name());
-
- // Final release so file and temp-dir can be removed.
- GlobalHistogramAllocator::ReleaseForTesting();
-}
-
-TEST_F(PersistentHistogramAllocatorTest, CreateSpareFile) {
- const char temp_name[] = "CreateSpareFileTest.pma";
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath temp_file = temp_dir.GetPath().AppendASCII(temp_name);
- const size_t temp_size = 64 << 10; // 64 KiB
-
- ASSERT_TRUE(GlobalHistogramAllocator::CreateSpareFile(temp_file, temp_size));
-
- File file(temp_file, File::FLAG_OPEN | File::FLAG_READ);
- ASSERT_TRUE(file.IsValid());
- EXPECT_EQ(static_cast<int64_t>(temp_size), file.GetLength());
-
- char buffer[256];
- for (size_t pos = 0; pos < temp_size; pos += sizeof(buffer)) {
- ASSERT_EQ(static_cast<int>(sizeof(buffer)),
- file.ReadAtCurrentPos(buffer, sizeof(buffer)));
- for (size_t i = 0; i < sizeof(buffer); ++i)
- EXPECT_EQ(0, buffer[i]);
- }
-}
-
-TEST_F(PersistentHistogramAllocatorTest, StatisticsRecorderMerge) {
- const char LinearHistogramName[] = "SRTLinearHistogram";
- const char SparseHistogramName[] = "SRTSparseHistogram";
- const size_t starting_sr_count = StatisticsRecorder::GetHistogramCount();
-
- // Create a local StatisticsRecorder in which the newly created histogram
- // will be recorded. The global allocator must be replaced after because the
- // act of releasing will cause the active SR to forget about all histograms
- // in the relased memory.
- std::unique_ptr<StatisticsRecorder> local_sr =
- StatisticsRecorder::CreateTemporaryForTesting();
- EXPECT_EQ(0U, StatisticsRecorder::GetHistogramCount());
- std::unique_ptr<GlobalHistogramAllocator> old_allocator =
- GlobalHistogramAllocator::ReleaseForTesting();
- GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0, "");
- ASSERT_TRUE(GlobalHistogramAllocator::Get());
-
- // Create a linear histogram for merge testing.
- HistogramBase* histogram1 =
- LinearHistogram::FactoryGet(LinearHistogramName, 1, 10, 10, 0);
- ASSERT_TRUE(histogram1);
- EXPECT_EQ(1U, StatisticsRecorder::GetHistogramCount());
- histogram1->Add(3);
- histogram1->Add(1);
- histogram1->Add(4);
- histogram1->AddCount(1, 4);
- histogram1->Add(6);
-
- // Create a sparse histogram for merge testing.
- HistogramBase* histogram2 =
- SparseHistogram::FactoryGet(SparseHistogramName, 0);
- ASSERT_TRUE(histogram2);
- EXPECT_EQ(2U, StatisticsRecorder::GetHistogramCount());
- histogram2->Add(3);
- histogram2->Add(1);
- histogram2->Add(4);
- histogram2->AddCount(1, 4);
- histogram2->Add(6);
-
- // Destroy the local SR and ensure that we're back to the initial state and
- // restore the global allocator. Histograms created in the local SR will
- // become unmanaged.
- std::unique_ptr<GlobalHistogramAllocator> new_allocator =
- GlobalHistogramAllocator::ReleaseForTesting();
- local_sr.reset();
- EXPECT_EQ(starting_sr_count, StatisticsRecorder::GetHistogramCount());
- GlobalHistogramAllocator::Set(std::move(old_allocator));
-
- // Create a "recovery" allocator using the same memory as the local one.
- PersistentHistogramAllocator recovery1(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(new_allocator->memory_allocator()->data()),
- new_allocator->memory_allocator()->size(), 0, 0, "", false));
- PersistentHistogramAllocator::Iterator histogram_iter1(&recovery1);
-
- // Get the histograms that were created locally (and forgotten) and merge
- // them into the global SR. New objects will be created.
- std::unique_ptr<HistogramBase> recovered;
- while (true) {
- recovered = histogram_iter1.GetNext();
- if (!recovered)
- break;
-
- recovery1.MergeHistogramDeltaToStatisticsRecorder(recovered.get());
- HistogramBase* found =
- StatisticsRecorder::FindHistogram(recovered->histogram_name());
- EXPECT_NE(recovered.get(), found);
- };
- EXPECT_EQ(starting_sr_count + 2, StatisticsRecorder::GetHistogramCount());
-
- // Check the merged histograms for accuracy.
- HistogramBase* found = StatisticsRecorder::FindHistogram(LinearHistogramName);
- ASSERT_TRUE(found);
- std::unique_ptr<HistogramSamples> snapshot = found->SnapshotSamples();
- EXPECT_EQ(found->SnapshotSamples()->TotalCount(), snapshot->TotalCount());
- EXPECT_EQ(1, snapshot->GetCount(3));
- EXPECT_EQ(5, snapshot->GetCount(1));
- EXPECT_EQ(1, snapshot->GetCount(4));
- EXPECT_EQ(1, snapshot->GetCount(6));
-
- found = StatisticsRecorder::FindHistogram(SparseHistogramName);
- ASSERT_TRUE(found);
- snapshot = found->SnapshotSamples();
- EXPECT_EQ(found->SnapshotSamples()->TotalCount(), snapshot->TotalCount());
- EXPECT_EQ(1, snapshot->GetCount(3));
- EXPECT_EQ(5, snapshot->GetCount(1));
- EXPECT_EQ(1, snapshot->GetCount(4));
- EXPECT_EQ(1, snapshot->GetCount(6));
-
- // Perform additional histogram increments.
- histogram1->AddCount(1, 3);
- histogram1->Add(6);
- histogram2->AddCount(1, 3);
- histogram2->Add(7);
-
- // Do another merge.
- PersistentHistogramAllocator recovery2(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(new_allocator->memory_allocator()->data()),
- new_allocator->memory_allocator()->size(), 0, 0, "", false));
- PersistentHistogramAllocator::Iterator histogram_iter2(&recovery2);
- while (true) {
- recovered = histogram_iter2.GetNext();
- if (!recovered)
- break;
- recovery2.MergeHistogramDeltaToStatisticsRecorder(recovered.get());
- };
- EXPECT_EQ(starting_sr_count + 2, StatisticsRecorder::GetHistogramCount());
-
- // And verify.
- found = StatisticsRecorder::FindHistogram(LinearHistogramName);
- snapshot = found->SnapshotSamples();
- EXPECT_EQ(found->SnapshotSamples()->TotalCount(), snapshot->TotalCount());
- EXPECT_EQ(1, snapshot->GetCount(3));
- EXPECT_EQ(8, snapshot->GetCount(1));
- EXPECT_EQ(1, snapshot->GetCount(4));
- EXPECT_EQ(2, snapshot->GetCount(6));
-
- found = StatisticsRecorder::FindHistogram(SparseHistogramName);
- snapshot = found->SnapshotSamples();
- EXPECT_EQ(found->SnapshotSamples()->TotalCount(), snapshot->TotalCount());
- EXPECT_EQ(1, snapshot->GetCount(3));
- EXPECT_EQ(8, snapshot->GetCount(1));
- EXPECT_EQ(1, snapshot->GetCount(4));
- EXPECT_EQ(1, snapshot->GetCount(6));
- EXPECT_EQ(1, snapshot->GetCount(7));
-}
-
-TEST_F(PersistentHistogramAllocatorTest, RangesDeDuplication) {
- // This corresponds to the "ranges_ref" field of the PersistentHistogramData
- // structure defined (privately) inside persistent_histogram_allocator.cc.
- const int kRangesRefIndex = 5;
-
- // Create two histograms with the same ranges.
- HistogramBase* histogram1 =
- Histogram::FactoryGet("TestHistogram1", 1, 1000, 10, 0);
- HistogramBase* histogram2 =
- Histogram::FactoryGet("TestHistogram2", 1, 1000, 10, 0);
- const uint32_t ranges_ref = static_cast<Histogram*>(histogram1)
- ->bucket_ranges()
- ->persistent_reference();
- ASSERT_NE(0U, ranges_ref);
- EXPECT_EQ(ranges_ref, static_cast<Histogram*>(histogram2)
- ->bucket_ranges()
- ->persistent_reference());
-
- // Make sure that the persistent data record is also correct. Two histograms
- // will be fetched; other allocations are not "iterable".
- PersistentMemoryAllocator::Iterator iter(allocator_);
- uint32_t type;
- uint32_t ref1 = iter.GetNext(&type);
- uint32_t ref2 = iter.GetNext(&type);
- EXPECT_EQ(0U, iter.GetNext(&type));
- EXPECT_NE(0U, ref1);
- EXPECT_NE(0U, ref2);
- EXPECT_NE(ref1, ref2);
-
- uint32_t* data1 =
- allocator_->GetAsArray<uint32_t>(ref1, 0, kRangesRefIndex + 1);
- uint32_t* data2 =
- allocator_->GetAsArray<uint32_t>(ref2, 0, kRangesRefIndex + 1);
- EXPECT_EQ(ranges_ref, data1[kRangesRefIndex]);
- EXPECT_EQ(ranges_ref, data2[kRangesRefIndex]);
-}
-
-} // namespace base
diff --git a/base/metrics/persistent_histogram_storage_unittest.cc b/base/metrics/persistent_histogram_storage_unittest.cc
deleted file mode 100644
index ed42068..0000000
--- a/base/metrics/persistent_histogram_storage_unittest.cc
+++ /dev/null
@@ -1,78 +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/metrics/persistent_histogram_storage.h"
-
-#include <memory>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Name of the allocator for storing histograms.
-constexpr char kTestHistogramAllocatorName[] = "TestMetrics";
-
-} // namespace
-
-class PersistentHistogramStorageTest : public testing::Test {
- protected:
- PersistentHistogramStorageTest() = default;
- ~PersistentHistogramStorageTest() override = default;
-
- // Creates a unique temporary directory, and sets the test storage directory.
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- test_storage_dir_ =
- temp_dir_path().AppendASCII(kTestHistogramAllocatorName);
- }
-
- // Gets the path to the temporary directory.
- const FilePath& temp_dir_path() { return temp_dir_.GetPath(); }
-
- const FilePath& test_storage_dir() { return test_storage_dir_; }
-
- private:
- // A temporary directory where all file IO operations take place.
- ScopedTempDir temp_dir_;
-
- // The directory into which metrics files are written.
- FilePath test_storage_dir_;
-
- DISALLOW_COPY_AND_ASSIGN(PersistentHistogramStorageTest);
-};
-
-// TODO(chengx): Re-enable the test on OS_IOS after issue 836789 is fixed.
-// PersistentHistogramStorage is only used on OS_WIN now, so disabling this
-// test on OS_IOS is fine.
-#if !defined(OS_NACL) && !defined(OS_IOS)
-TEST_F(PersistentHistogramStorageTest, HistogramWriteTest) {
- auto persistent_histogram_storage =
- std::make_unique<PersistentHistogramStorage>(
- kTestHistogramAllocatorName,
- PersistentHistogramStorage::StorageDirManagement::kCreate);
-
- persistent_histogram_storage->set_storage_base_dir(temp_dir_path());
-
- // Log some random data.
- UMA_HISTOGRAM_BOOLEAN("Some.Test.Metric", true);
-
- // Deleting the object causes the data to be written to the disk.
- persistent_histogram_storage.reset();
-
- // The storage directory and the histogram file are created during the
- // destruction of the PersistentHistogramStorage instance.
- EXPECT_TRUE(DirectoryExists(test_storage_dir()));
- EXPECT_FALSE(IsDirectoryEmpty(test_storage_dir()));
-}
-#endif // !defined(OS_NACL) && !defined(OS_IOS)
-
-} // namespace base
diff --git a/base/metrics/persistent_memory_allocator_unittest.cc b/base/metrics/persistent_memory_allocator_unittest.cc
deleted file mode 100644
index 75e4faa..0000000
--- a/base/metrics/persistent_memory_allocator_unittest.cc
+++ /dev/null
@@ -1,1001 +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/metrics/persistent_memory_allocator.h"
-
-#include <memory>
-
-#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/shared_memory.h"
-#include "base/metrics/histogram.h"
-#include "base/rand_util.h"
-#include "base/strings/safe_sprintf.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gmock/include/gmock/gmock.h"
-
-namespace base {
-
-namespace {
-
-const uint32_t TEST_MEMORY_SIZE = 1 << 20; // 1 MiB
-const uint32_t TEST_MEMORY_PAGE = 64 << 10; // 64 KiB
-const uint32_t TEST_ID = 12345;
-const char TEST_NAME[] = "TestAllocator";
-
-void SetFileLength(const base::FilePath& path, size_t length) {
- {
- File file(path, File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE);
- DCHECK(file.IsValid());
- ASSERT_TRUE(file.SetLength(static_cast<int64_t>(length)));
- }
-
- int64_t actual_length;
- DCHECK(GetFileSize(path, &actual_length));
- DCHECK_EQ(length, static_cast<size_t>(actual_length));
-}
-
-} // namespace
-
-typedef PersistentMemoryAllocator::Reference Reference;
-
-class PersistentMemoryAllocatorTest : public testing::Test {
- public:
- // This can't be statically initialized because it's value isn't defined
- // in the PersistentMemoryAllocator header file. Instead, it's simply set
- // in the constructor.
- uint32_t kAllocAlignment;
-
- struct TestObject1 {
- static constexpr uint32_t kPersistentTypeId = 1;
- static constexpr size_t kExpectedInstanceSize = 4 + 1 + 3;
- int32_t onething;
- char oranother;
- };
-
- struct TestObject2 {
- static constexpr uint32_t kPersistentTypeId = 2;
- static constexpr size_t kExpectedInstanceSize = 8 + 4 + 4 + 8 + 8;
- int64_t thiis;
- int32_t that;
- float andthe;
- double other;
- char thing[8];
- };
-
- PersistentMemoryAllocatorTest() {
- kAllocAlignment = GetAllocAlignment();
- mem_segment_.reset(new char[TEST_MEMORY_SIZE]);
- }
-
- void SetUp() override {
- allocator_.reset();
- ::memset(mem_segment_.get(), 0, TEST_MEMORY_SIZE);
- allocator_.reset(new PersistentMemoryAllocator(
- mem_segment_.get(), TEST_MEMORY_SIZE, TEST_MEMORY_PAGE,
- TEST_ID, TEST_NAME, false));
- }
-
- void TearDown() override {
- allocator_.reset();
- }
-
- unsigned CountIterables() {
- PersistentMemoryAllocator::Iterator iter(allocator_.get());
- uint32_t type;
- unsigned count = 0;
- while (iter.GetNext(&type) != 0) {
- ++count;
- }
- return count;
- }
-
- static uint32_t GetAllocAlignment() {
- return PersistentMemoryAllocator::kAllocAlignment;
- }
-
- protected:
- std::unique_ptr<char[]> mem_segment_;
- std::unique_ptr<PersistentMemoryAllocator> allocator_;
-};
-
-TEST_F(PersistentMemoryAllocatorTest, AllocateAndIterate) {
- allocator_->CreateTrackingHistograms(allocator_->Name());
-
- std::string base_name(TEST_NAME);
- EXPECT_EQ(TEST_ID, allocator_->Id());
- EXPECT_TRUE(allocator_->used_histogram_);
- EXPECT_EQ("UMA.PersistentAllocator." + base_name + ".UsedPct",
- allocator_->used_histogram_->histogram_name());
- EXPECT_EQ(PersistentMemoryAllocator::MEMORY_INITIALIZED,
- allocator_->GetMemoryState());
-
- // Get base memory info for later comparison.
- PersistentMemoryAllocator::MemoryInfo meminfo0;
- allocator_->GetMemoryInfo(&meminfo0);
- EXPECT_EQ(TEST_MEMORY_SIZE, meminfo0.total);
- EXPECT_GT(meminfo0.total, meminfo0.free);
-
- // Validate allocation of test object and make sure it can be referenced
- // and all metadata looks correct.
- TestObject1* obj1 = allocator_->New<TestObject1>();
- ASSERT_TRUE(obj1);
- Reference block1 = allocator_->GetAsReference(obj1);
- ASSERT_NE(0U, block1);
- EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject1>(block1));
- EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject2>(block1));
- EXPECT_LE(sizeof(TestObject1), allocator_->GetAllocSize(block1));
- EXPECT_GT(sizeof(TestObject1) + kAllocAlignment,
- allocator_->GetAllocSize(block1));
- PersistentMemoryAllocator::MemoryInfo meminfo1;
- allocator_->GetMemoryInfo(&meminfo1);
- EXPECT_EQ(meminfo0.total, meminfo1.total);
- EXPECT_GT(meminfo0.free, meminfo1.free);
-
- // Verify that pointers can be turned back into references and that invalid
- // addresses return null.
- char* memory1 = allocator_->GetAsArray<char>(block1, 1, 1);
- ASSERT_TRUE(memory1);
- EXPECT_EQ(block1, allocator_->GetAsReference(memory1, 0));
- EXPECT_EQ(block1, allocator_->GetAsReference(memory1, 1));
- EXPECT_EQ(0U, allocator_->GetAsReference(memory1, 2));
- EXPECT_EQ(0U, allocator_->GetAsReference(memory1 + 1, 0));
- EXPECT_EQ(0U, allocator_->GetAsReference(memory1 + 16, 0));
- EXPECT_EQ(0U, allocator_->GetAsReference(nullptr, 0));
- EXPECT_EQ(0U, allocator_->GetAsReference(&base_name, 0));
-
- // Ensure that the test-object can be made iterable.
- PersistentMemoryAllocator::Iterator iter1a(allocator_.get());
- EXPECT_EQ(0U, iter1a.GetLast());
- uint32_t type;
- EXPECT_EQ(0U, iter1a.GetNext(&type));
- allocator_->MakeIterable(block1);
- EXPECT_EQ(block1, iter1a.GetNext(&type));
- EXPECT_EQ(1U, type);
- EXPECT_EQ(block1, iter1a.GetLast());
- EXPECT_EQ(0U, iter1a.GetNext(&type));
- EXPECT_EQ(block1, iter1a.GetLast());
-
- // Create second test-object and ensure everything is good and it cannot
- // be confused with test-object of another type.
- TestObject2* obj2 = allocator_->New<TestObject2>();
- ASSERT_TRUE(obj2);
- Reference block2 = allocator_->GetAsReference(obj2);
- ASSERT_NE(0U, block2);
- EXPECT_NE(nullptr, allocator_->GetAsObject<TestObject2>(block2));
- EXPECT_EQ(nullptr, allocator_->GetAsObject<TestObject1>(block2));
- EXPECT_LE(sizeof(TestObject2), allocator_->GetAllocSize(block2));
- EXPECT_GT(sizeof(TestObject2) + kAllocAlignment,
- allocator_->GetAllocSize(block2));
- PersistentMemoryAllocator::MemoryInfo meminfo2;
- allocator_->GetMemoryInfo(&meminfo2);
- EXPECT_EQ(meminfo1.total, meminfo2.total);
- EXPECT_GT(meminfo1.free, meminfo2.free);
-
- // Ensure that second test-object can also be made iterable.
- allocator_->MakeIterable(obj2);
- EXPECT_EQ(block2, iter1a.GetNext(&type));
- EXPECT_EQ(2U, type);
- EXPECT_EQ(block2, iter1a.GetLast());
- EXPECT_EQ(0U, iter1a.GetNext(&type));
- EXPECT_EQ(block2, iter1a.GetLast());
-
- // Check that the iterator can be reset to the beginning.
- iter1a.Reset();
- EXPECT_EQ(0U, iter1a.GetLast());
- EXPECT_EQ(block1, iter1a.GetNext(&type));
- EXPECT_EQ(block1, iter1a.GetLast());
- EXPECT_EQ(block2, iter1a.GetNext(&type));
- EXPECT_EQ(block2, iter1a.GetLast());
- EXPECT_EQ(0U, iter1a.GetNext(&type));
-
- // Check that the iterator can be reset to an arbitrary location.
- iter1a.Reset(block1);
- EXPECT_EQ(block1, iter1a.GetLast());
- EXPECT_EQ(block2, iter1a.GetNext(&type));
- EXPECT_EQ(block2, iter1a.GetLast());
- EXPECT_EQ(0U, iter1a.GetNext(&type));
-
- // Check that iteration can begin after an arbitrary location.
- PersistentMemoryAllocator::Iterator iter1b(allocator_.get(), block1);
- EXPECT_EQ(block2, iter1b.GetNext(&type));
- EXPECT_EQ(0U, iter1b.GetNext(&type));
-
- // Ensure nothing has gone noticably wrong.
- EXPECT_FALSE(allocator_->IsFull());
- EXPECT_FALSE(allocator_->IsCorrupt());
-
- // Check the internal histogram record of used memory.
- allocator_->UpdateTrackingHistograms();
- std::unique_ptr<HistogramSamples> used_samples(
- allocator_->used_histogram_->SnapshotSamples());
- EXPECT_TRUE(used_samples);
- EXPECT_EQ(1, used_samples->TotalCount());
-
- // Check that an object's type can be changed.
- EXPECT_EQ(2U, allocator_->GetType(block2));
- allocator_->ChangeType(block2, 3, 2, false);
- EXPECT_EQ(3U, allocator_->GetType(block2));
- allocator_->New<TestObject2>(block2, 3, false);
- EXPECT_EQ(2U, allocator_->GetType(block2));
-
- // Create second allocator (read/write) using the same memory segment.
- std::unique_ptr<PersistentMemoryAllocator> allocator2(
- new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE,
- TEST_MEMORY_PAGE, 0, "", false));
- EXPECT_EQ(TEST_ID, allocator2->Id());
- EXPECT_FALSE(allocator2->used_histogram_);
-
- // Ensure that iteration and access through second allocator works.
- PersistentMemoryAllocator::Iterator iter2(allocator2.get());
- EXPECT_EQ(block1, iter2.GetNext(&type));
- EXPECT_EQ(block2, iter2.GetNext(&type));
- EXPECT_EQ(0U, iter2.GetNext(&type));
- EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject1>(block1));
- EXPECT_NE(nullptr, allocator2->GetAsObject<TestObject2>(block2));
-
- // Create a third allocator (read-only) using the same memory segment.
- std::unique_ptr<const PersistentMemoryAllocator> allocator3(
- new PersistentMemoryAllocator(mem_segment_.get(), TEST_MEMORY_SIZE,
- TEST_MEMORY_PAGE, 0, "", true));
- EXPECT_EQ(TEST_ID, allocator3->Id());
- EXPECT_FALSE(allocator3->used_histogram_);
-
- // Ensure that iteration and access through third allocator works.
- PersistentMemoryAllocator::Iterator iter3(allocator3.get());
- EXPECT_EQ(block1, iter3.GetNext(&type));
- EXPECT_EQ(block2, iter3.GetNext(&type));
- EXPECT_EQ(0U, iter3.GetNext(&type));
- EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject1>(block1));
- EXPECT_NE(nullptr, allocator3->GetAsObject<TestObject2>(block2));
-
- // Ensure that GetNextOfType works.
- PersistentMemoryAllocator::Iterator iter1c(allocator_.get());
- EXPECT_EQ(block2, iter1c.GetNextOfType<TestObject2>());
- EXPECT_EQ(0U, iter1c.GetNextOfType(2));
-
- // Ensure that GetNextOfObject works.
- PersistentMemoryAllocator::Iterator iter1d(allocator_.get());
- EXPECT_EQ(obj2, iter1d.GetNextOfObject<TestObject2>());
- EXPECT_EQ(nullptr, iter1d.GetNextOfObject<TestObject2>());
-
- // Ensure that deleting an object works.
- allocator_->Delete(obj2);
- PersistentMemoryAllocator::Iterator iter1z(allocator_.get());
- EXPECT_EQ(nullptr, iter1z.GetNextOfObject<TestObject2>());
-
- // Ensure that the memory state can be set.
- allocator_->SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED);
- EXPECT_EQ(PersistentMemoryAllocator::MEMORY_DELETED,
- allocator_->GetMemoryState());
-}
-
-TEST_F(PersistentMemoryAllocatorTest, PageTest) {
- // This allocation will go into the first memory page.
- Reference block1 = allocator_->Allocate(TEST_MEMORY_PAGE / 2, 1);
- EXPECT_LT(0U, block1);
- EXPECT_GT(TEST_MEMORY_PAGE, block1);
-
- // This allocation won't fit in same page as previous block.
- Reference block2 =
- allocator_->Allocate(TEST_MEMORY_PAGE - 2 * kAllocAlignment, 2);
- EXPECT_EQ(TEST_MEMORY_PAGE, block2);
-
- // This allocation will also require a new page.
- Reference block3 = allocator_->Allocate(2 * kAllocAlignment + 99, 3);
- EXPECT_EQ(2U * TEST_MEMORY_PAGE, block3);
-}
-
-// A simple thread that takes an allocator and repeatedly allocates random-
-// sized chunks from it until no more can be done.
-class AllocatorThread : public SimpleThread {
- public:
- AllocatorThread(const std::string& name,
- void* base,
- uint32_t size,
- uint32_t page_size)
- : SimpleThread(name, Options()),
- count_(0),
- iterable_(0),
- allocator_(base, size, page_size, 0, std::string(), false) {}
-
- void Run() override {
- for (;;) {
- uint32_t size = RandInt(1, 99);
- uint32_t type = RandInt(100, 999);
- Reference block = allocator_.Allocate(size, type);
- if (!block)
- break;
-
- count_++;
- if (RandInt(0, 1)) {
- allocator_.MakeIterable(block);
- iterable_++;
- }
- }
- }
-
- unsigned iterable() { return iterable_; }
- unsigned count() { return count_; }
-
- private:
- unsigned count_;
- unsigned iterable_;
- PersistentMemoryAllocator allocator_;
-};
-
-// Test parallel allocation/iteration and ensure consistency across all
-// instances.
-TEST_F(PersistentMemoryAllocatorTest, ParallelismTest) {
- void* memory = mem_segment_.get();
- AllocatorThread t1("t1", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t2("t2", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t3("t3", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t4("t4", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t5("t5", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
-
- t1.Start();
- t2.Start();
- t3.Start();
- t4.Start();
- t5.Start();
-
- unsigned last_count = 0;
- do {
- unsigned count = CountIterables();
- EXPECT_LE(last_count, count);
- } while (!allocator_->IsCorrupt() && !allocator_->IsFull());
-
- t1.Join();
- t2.Join();
- t3.Join();
- t4.Join();
- t5.Join();
-
- EXPECT_FALSE(allocator_->IsCorrupt());
- EXPECT_TRUE(allocator_->IsFull());
- EXPECT_EQ(CountIterables(),
- t1.iterable() + t2.iterable() + t3.iterable() + t4.iterable() +
- t5.iterable());
-}
-
-// A simple thread that counts objects by iterating through an allocator.
-class CounterThread : public SimpleThread {
- public:
- CounterThread(const std::string& name,
- PersistentMemoryAllocator::Iterator* iterator,
- Lock* lock,
- ConditionVariable* condition,
- bool* wake_up)
- : SimpleThread(name, Options()),
- iterator_(iterator),
- lock_(lock),
- condition_(condition),
- count_(0),
- wake_up_(wake_up) {}
-
- void Run() override {
- // Wait so all threads can start at approximately the same time.
- // Best performance comes from releasing a single worker which then
- // releases the next, etc., etc.
- {
- AutoLock autolock(*lock_);
-
- // Before calling Wait(), make sure that the wake up condition
- // has not already passed. Also, since spurious signal events
- // are possible, check the condition in a while loop to make
- // sure that the wake up condition is met when this thread
- // returns from the Wait().
- // See usage comments in src/base/synchronization/condition_variable.h.
- while (!*wake_up_) {
- condition_->Wait();
- condition_->Signal();
- }
- }
-
- uint32_t type;
- while (iterator_->GetNext(&type) != 0) {
- ++count_;
- }
- }
-
- unsigned count() { return count_; }
-
- private:
- PersistentMemoryAllocator::Iterator* iterator_;
- Lock* lock_;
- ConditionVariable* condition_;
- unsigned count_;
- bool* wake_up_;
-
- DISALLOW_COPY_AND_ASSIGN(CounterThread);
-};
-
-// Ensure that parallel iteration returns the same number of objects as
-// single-threaded iteration.
-TEST_F(PersistentMemoryAllocatorTest, IteratorParallelismTest) {
- // Fill the memory segment with random allocations.
- unsigned iterable_count = 0;
- for (;;) {
- uint32_t size = RandInt(1, 99);
- uint32_t type = RandInt(100, 999);
- Reference block = allocator_->Allocate(size, type);
- if (!block)
- break;
- allocator_->MakeIterable(block);
- ++iterable_count;
- }
- EXPECT_FALSE(allocator_->IsCorrupt());
- EXPECT_TRUE(allocator_->IsFull());
- EXPECT_EQ(iterable_count, CountIterables());
-
- PersistentMemoryAllocator::Iterator iter(allocator_.get());
- Lock lock;
- ConditionVariable condition(&lock);
- bool wake_up = false;
-
- CounterThread t1("t1", &iter, &lock, &condition, &wake_up);
- CounterThread t2("t2", &iter, &lock, &condition, &wake_up);
- CounterThread t3("t3", &iter, &lock, &condition, &wake_up);
- CounterThread t4("t4", &iter, &lock, &condition, &wake_up);
- CounterThread t5("t5", &iter, &lock, &condition, &wake_up);
-
- t1.Start();
- t2.Start();
- t3.Start();
- t4.Start();
- t5.Start();
-
- // Take the lock and set the wake up condition to true. This helps to
- // avoid a race condition where the Signal() event is called before
- // all the threads have reached the Wait() and thus never get woken up.
- {
- AutoLock autolock(lock);
- wake_up = true;
- }
-
- // This will release all the waiting threads.
- condition.Signal();
-
- t1.Join();
- t2.Join();
- t3.Join();
- t4.Join();
- t5.Join();
-
- EXPECT_EQ(iterable_count,
- t1.count() + t2.count() + t3.count() + t4.count() + t5.count());
-
-#if 0
- // These ensure that the threads don't run sequentially. It shouldn't be
- // enabled in general because it could lead to a flaky test if it happens
- // simply by chance but it is useful during development to ensure that the
- // test is working correctly.
- EXPECT_NE(iterable_count, t1.count());
- EXPECT_NE(iterable_count, t2.count());
- EXPECT_NE(iterable_count, t3.count());
- EXPECT_NE(iterable_count, t4.count());
- EXPECT_NE(iterable_count, t5.count());
-#endif
-}
-
-TEST_F(PersistentMemoryAllocatorTest, DelayedAllocationTest) {
- std::atomic<Reference> ref1, ref2;
- ref1.store(0, std::memory_order_relaxed);
- ref2.store(0, std::memory_order_relaxed);
- DelayedPersistentAllocation da1(allocator_.get(), &ref1, 1001, 100, true);
- DelayedPersistentAllocation da2a(allocator_.get(), &ref2, 2002, 200, 0, true);
- DelayedPersistentAllocation da2b(allocator_.get(), &ref2, 2002, 200, 5, true);
-
- // Nothing should yet have been allocated.
- uint32_t type;
- PersistentMemoryAllocator::Iterator iter(allocator_.get());
- EXPECT_EQ(0U, iter.GetNext(&type));
-
- // Do first delayed allocation and check that a new persistent object exists.
- EXPECT_EQ(0U, da1.reference());
- void* mem1 = da1.Get();
- ASSERT_TRUE(mem1);
- EXPECT_NE(0U, da1.reference());
- EXPECT_EQ(allocator_->GetAsReference(mem1, 1001),
- ref1.load(std::memory_order_relaxed));
- EXPECT_NE(0U, iter.GetNext(&type));
- EXPECT_EQ(1001U, type);
- EXPECT_EQ(0U, iter.GetNext(&type));
-
- // Do second delayed allocation and check.
- void* mem2a = da2a.Get();
- ASSERT_TRUE(mem2a);
- EXPECT_EQ(allocator_->GetAsReference(mem2a, 2002),
- ref2.load(std::memory_order_relaxed));
- EXPECT_NE(0U, iter.GetNext(&type));
- EXPECT_EQ(2002U, type);
- EXPECT_EQ(0U, iter.GetNext(&type));
-
- // Third allocation should just return offset into second allocation.
- void* mem2b = da2b.Get();
- ASSERT_TRUE(mem2b);
- EXPECT_EQ(0U, iter.GetNext(&type));
- EXPECT_EQ(reinterpret_cast<uintptr_t>(mem2a) + 5,
- reinterpret_cast<uintptr_t>(mem2b));
-}
-
-// This test doesn't verify anything other than it doesn't crash. Its goal
-// is to find coding errors that aren't otherwise tested for, much like a
-// "fuzzer" would.
-// This test is suppsoed to fail on TSAN bot (crbug.com/579867).
-#if defined(THREAD_SANITIZER)
-#define MAYBE_CorruptionTest DISABLED_CorruptionTest
-#else
-#define MAYBE_CorruptionTest CorruptionTest
-#endif
-TEST_F(PersistentMemoryAllocatorTest, MAYBE_CorruptionTest) {
- char* memory = mem_segment_.get();
- AllocatorThread t1("t1", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t2("t2", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t3("t3", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t4("t4", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
- AllocatorThread t5("t5", memory, TEST_MEMORY_SIZE, TEST_MEMORY_PAGE);
-
- t1.Start();
- t2.Start();
- t3.Start();
- t4.Start();
- t5.Start();
-
- do {
- size_t offset = RandInt(0, TEST_MEMORY_SIZE - 1);
- char value = RandInt(0, 255);
- memory[offset] = value;
- } while (!allocator_->IsCorrupt() && !allocator_->IsFull());
-
- t1.Join();
- t2.Join();
- t3.Join();
- t4.Join();
- t5.Join();
-
- CountIterables();
-}
-
-// Attempt to cause crashes or loops by expressly creating dangerous conditions.
-TEST_F(PersistentMemoryAllocatorTest, MaliciousTest) {
- Reference block1 = allocator_->Allocate(sizeof(TestObject1), 1);
- Reference block2 = allocator_->Allocate(sizeof(TestObject1), 2);
- Reference block3 = allocator_->Allocate(sizeof(TestObject1), 3);
- Reference block4 = allocator_->Allocate(sizeof(TestObject1), 3);
- Reference block5 = allocator_->Allocate(sizeof(TestObject1), 3);
- allocator_->MakeIterable(block1);
- allocator_->MakeIterable(block2);
- allocator_->MakeIterable(block3);
- allocator_->MakeIterable(block4);
- allocator_->MakeIterable(block5);
- EXPECT_EQ(5U, CountIterables());
- EXPECT_FALSE(allocator_->IsCorrupt());
-
- // Create loop in iterable list and ensure it doesn't hang. The return value
- // from CountIterables() in these cases is unpredictable. If there is a
- // failure, the call will hang and the test killed for taking too long.
- uint32_t* header4 = (uint32_t*)(mem_segment_.get() + block4);
- EXPECT_EQ(block5, header4[3]);
- header4[3] = block4;
- CountIterables(); // loop: 1-2-3-4-4
- EXPECT_TRUE(allocator_->IsCorrupt());
-
- // Test where loop goes back to previous block.
- header4[3] = block3;
- CountIterables(); // loop: 1-2-3-4-3
-
- // Test where loop goes back to the beginning.
- header4[3] = block1;
- CountIterables(); // loop: 1-2-3-4-1
-}
-
-
-//----- LocalPersistentMemoryAllocator -----------------------------------------
-
-TEST(LocalPersistentMemoryAllocatorTest, CreationTest) {
- LocalPersistentMemoryAllocator allocator(TEST_MEMORY_SIZE, 42, "");
- EXPECT_EQ(42U, allocator.Id());
- EXPECT_NE(0U, allocator.Allocate(24, 1));
- EXPECT_FALSE(allocator.IsFull());
- EXPECT_FALSE(allocator.IsCorrupt());
-}
-
-
-//----- SharedPersistentMemoryAllocator ----------------------------------------
-
-TEST(SharedPersistentMemoryAllocatorTest, CreationTest) {
- SharedMemoryHandle shared_handle_1;
- SharedMemoryHandle shared_handle_2;
-
- PersistentMemoryAllocator::MemoryInfo meminfo1;
- Reference r123, r456, r789;
- {
- std::unique_ptr<SharedMemory> shmem1(new SharedMemory());
- ASSERT_TRUE(shmem1->CreateAndMapAnonymous(TEST_MEMORY_SIZE));
- SharedPersistentMemoryAllocator local(std::move(shmem1), TEST_ID, "",
- false);
- EXPECT_FALSE(local.IsReadonly());
- r123 = local.Allocate(123, 123);
- r456 = local.Allocate(456, 456);
- r789 = local.Allocate(789, 789);
- local.MakeIterable(r123);
- local.ChangeType(r456, 654, 456, false);
- local.MakeIterable(r789);
- local.GetMemoryInfo(&meminfo1);
- EXPECT_FALSE(local.IsFull());
- EXPECT_FALSE(local.IsCorrupt());
-
- shared_handle_1 = local.shared_memory()->handle().Duplicate();
- ASSERT_TRUE(shared_handle_1.IsValid());
- shared_handle_2 = local.shared_memory()->handle().Duplicate();
- ASSERT_TRUE(shared_handle_2.IsValid());
- }
-
- // Read-only test.
- std::unique_ptr<SharedMemory> shmem2(new SharedMemory(shared_handle_1,
- /*readonly=*/true));
- ASSERT_TRUE(shmem2->Map(TEST_MEMORY_SIZE));
-
- SharedPersistentMemoryAllocator shalloc2(std::move(shmem2), 0, "", true);
- EXPECT_TRUE(shalloc2.IsReadonly());
- EXPECT_EQ(TEST_ID, shalloc2.Id());
- EXPECT_FALSE(shalloc2.IsFull());
- EXPECT_FALSE(shalloc2.IsCorrupt());
-
- PersistentMemoryAllocator::Iterator iter2(&shalloc2);
- uint32_t type;
- EXPECT_EQ(r123, iter2.GetNext(&type));
- EXPECT_EQ(r789, iter2.GetNext(&type));
- EXPECT_EQ(0U, iter2.GetNext(&type));
-
- EXPECT_EQ(123U, shalloc2.GetType(r123));
- EXPECT_EQ(654U, shalloc2.GetType(r456));
- EXPECT_EQ(789U, shalloc2.GetType(r789));
-
- PersistentMemoryAllocator::MemoryInfo meminfo2;
- shalloc2.GetMemoryInfo(&meminfo2);
- EXPECT_EQ(meminfo1.total, meminfo2.total);
- EXPECT_EQ(meminfo1.free, meminfo2.free);
-
- // Read/write test.
- std::unique_ptr<SharedMemory> shmem3(new SharedMemory(shared_handle_2,
- /*readonly=*/false));
- ASSERT_TRUE(shmem3->Map(TEST_MEMORY_SIZE));
-
- SharedPersistentMemoryAllocator shalloc3(std::move(shmem3), 0, "", false);
- EXPECT_FALSE(shalloc3.IsReadonly());
- EXPECT_EQ(TEST_ID, shalloc3.Id());
- EXPECT_FALSE(shalloc3.IsFull());
- EXPECT_FALSE(shalloc3.IsCorrupt());
-
- PersistentMemoryAllocator::Iterator iter3(&shalloc3);
- EXPECT_EQ(r123, iter3.GetNext(&type));
- EXPECT_EQ(r789, iter3.GetNext(&type));
- EXPECT_EQ(0U, iter3.GetNext(&type));
-
- EXPECT_EQ(123U, shalloc3.GetType(r123));
- EXPECT_EQ(654U, shalloc3.GetType(r456));
- EXPECT_EQ(789U, shalloc3.GetType(r789));
-
- PersistentMemoryAllocator::MemoryInfo meminfo3;
- shalloc3.GetMemoryInfo(&meminfo3);
- EXPECT_EQ(meminfo1.total, meminfo3.total);
- EXPECT_EQ(meminfo1.free, meminfo3.free);
-
- // Interconnectivity test.
- Reference obj = shalloc3.Allocate(42, 42);
- ASSERT_TRUE(obj);
- shalloc3.MakeIterable(obj);
- EXPECT_EQ(obj, iter2.GetNext(&type));
- EXPECT_EQ(42U, type);
-
- // Clear-on-change test.
- Reference data_ref = shalloc3.Allocate(sizeof(int) * 4, 911);
- int* data = shalloc3.GetAsArray<int>(data_ref, 911, 4);
- ASSERT_TRUE(data);
- data[0] = 0;
- data[1] = 1;
- data[2] = 2;
- data[3] = 3;
- ASSERT_TRUE(shalloc3.ChangeType(data_ref, 119, 911, false));
- EXPECT_EQ(0, data[0]);
- EXPECT_EQ(1, data[1]);
- EXPECT_EQ(2, data[2]);
- EXPECT_EQ(3, data[3]);
- ASSERT_TRUE(shalloc3.ChangeType(data_ref, 191, 119, true));
- EXPECT_EQ(0, data[0]);
- EXPECT_EQ(0, data[1]);
- EXPECT_EQ(0, data[2]);
- EXPECT_EQ(0, data[3]);
-}
-
-
-#if !defined(OS_NACL)
-//----- FilePersistentMemoryAllocator ------------------------------------------
-
-TEST(FilePersistentMemoryAllocatorTest, CreationTest) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("persistent_memory");
-
- PersistentMemoryAllocator::MemoryInfo meminfo1;
- Reference r123, r456, r789;
- {
- LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, "");
- EXPECT_FALSE(local.IsReadonly());
- r123 = local.Allocate(123, 123);
- r456 = local.Allocate(456, 456);
- r789 = local.Allocate(789, 789);
- local.MakeIterable(r123);
- local.ChangeType(r456, 654, 456, false);
- local.MakeIterable(r789);
- local.GetMemoryInfo(&meminfo1);
- EXPECT_FALSE(local.IsFull());
- EXPECT_FALSE(local.IsCorrupt());
-
- File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE);
- ASSERT_TRUE(writer.IsValid());
- writer.Write(0, (const char*)local.data(), local.used());
- }
-
- std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
- mmfile->Initialize(file_path);
- EXPECT_TRUE(mmfile->IsValid());
- const size_t mmlength = mmfile->length();
- EXPECT_GE(meminfo1.total, mmlength);
-
- FilePersistentMemoryAllocator file(std::move(mmfile), 0, 0, "", false);
- EXPECT_FALSE(file.IsReadonly());
- EXPECT_EQ(TEST_ID, file.Id());
- EXPECT_FALSE(file.IsFull());
- EXPECT_FALSE(file.IsCorrupt());
-
- PersistentMemoryAllocator::Iterator iter(&file);
- uint32_t type;
- EXPECT_EQ(r123, iter.GetNext(&type));
- EXPECT_EQ(r789, iter.GetNext(&type));
- EXPECT_EQ(0U, iter.GetNext(&type));
-
- EXPECT_EQ(123U, file.GetType(r123));
- EXPECT_EQ(654U, file.GetType(r456));
- EXPECT_EQ(789U, file.GetType(r789));
-
- PersistentMemoryAllocator::MemoryInfo meminfo2;
- file.GetMemoryInfo(&meminfo2);
- EXPECT_GE(meminfo1.total, meminfo2.total);
- EXPECT_GE(meminfo1.free, meminfo2.free);
- EXPECT_EQ(mmlength, meminfo2.total);
- EXPECT_EQ(0U, meminfo2.free);
-
- // There's no way of knowing if Flush actually does anything but at least
- // verify that it runs without CHECK violations.
- file.Flush(false);
- file.Flush(true);
-}
-
-TEST(FilePersistentMemoryAllocatorTest, ExtendTest) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("extend_test");
- MemoryMappedFile::Region region = {0, 16 << 10}; // 16KiB maximum size.
-
- // Start with a small but valid file of persistent data.
- ASSERT_FALSE(PathExists(file_path));
- {
- LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, "");
- local.Allocate(1, 1);
- local.Allocate(11, 11);
-
- File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE);
- ASSERT_TRUE(writer.IsValid());
- writer.Write(0, (const char*)local.data(), local.used());
- }
- ASSERT_TRUE(PathExists(file_path));
- int64_t before_size;
- ASSERT_TRUE(GetFileSize(file_path, &before_size));
-
- // Map it as an extendable read/write file and append to it.
- {
- std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
- mmfile->Initialize(
- File(file_path, File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE),
- region, MemoryMappedFile::READ_WRITE_EXTEND);
- FilePersistentMemoryAllocator allocator(std::move(mmfile), region.size, 0,
- "", false);
- EXPECT_EQ(static_cast<size_t>(before_size), allocator.used());
-
- allocator.Allocate(111, 111);
- EXPECT_LT(static_cast<size_t>(before_size), allocator.used());
- }
-
- // Validate that append worked.
- int64_t after_size;
- ASSERT_TRUE(GetFileSize(file_path, &after_size));
- EXPECT_LT(before_size, after_size);
-
- // Verify that it's still an acceptable file.
- {
- std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
- mmfile->Initialize(
- File(file_path, File::FLAG_OPEN | File::FLAG_READ | File::FLAG_WRITE),
- region, MemoryMappedFile::READ_WRITE_EXTEND);
- EXPECT_TRUE(FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true));
- EXPECT_TRUE(
- FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, false));
- }
-}
-
-TEST(FilePersistentMemoryAllocatorTest, AcceptableTest) {
- const uint32_t kAllocAlignment =
- PersistentMemoryAllocatorTest::GetAllocAlignment();
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
-
- LocalPersistentMemoryAllocator local(TEST_MEMORY_SIZE, TEST_ID, "");
- local.MakeIterable(local.Allocate(1, 1));
- local.MakeIterable(local.Allocate(11, 11));
- const size_t minsize = local.used();
- std::unique_ptr<char[]> garbage(new char[minsize]);
- RandBytes(garbage.get(), minsize);
-
- std::unique_ptr<MemoryMappedFile> mmfile;
- char filename[100];
- for (size_t filesize = minsize; filesize > 0; --filesize) {
- strings::SafeSPrintf(filename, "memory_%d_A", filesize);
- FilePath file_path = temp_dir.GetPath().AppendASCII(filename);
- ASSERT_FALSE(PathExists(file_path));
- {
- File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE);
- ASSERT_TRUE(writer.IsValid());
- writer.Write(0, (const char*)local.data(), filesize);
- }
- ASSERT_TRUE(PathExists(file_path));
-
- // Request read/write access for some sizes that are a multple of the
- // allocator's alignment size. The allocator is strict about file size
- // being a multiple of its internal alignment when doing read/write access.
- const bool read_only = (filesize % (2 * kAllocAlignment)) != 0;
- const uint32_t file_flags =
- File::FLAG_OPEN | File::FLAG_READ | (read_only ? 0 : File::FLAG_WRITE);
- const MemoryMappedFile::Access map_access =
- read_only ? MemoryMappedFile::READ_ONLY : MemoryMappedFile::READ_WRITE;
-
- mmfile.reset(new MemoryMappedFile());
- mmfile->Initialize(File(file_path, file_flags), map_access);
- EXPECT_EQ(filesize, mmfile->length());
- if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, read_only)) {
- // Make sure construction doesn't crash. It will, however, cause
- // error messages warning about about a corrupted memory segment.
- FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, "",
- read_only);
- // Also make sure that iteration doesn't crash.
- PersistentMemoryAllocator::Iterator iter(&allocator);
- uint32_t type_id;
- Reference ref;
- while ((ref = iter.GetNext(&type_id)) != 0) {
- const char* data = allocator.GetAsArray<char>(
- ref, 0, PersistentMemoryAllocator::kSizeAny);
- uint32_t type = allocator.GetType(ref);
- size_t size = allocator.GetAllocSize(ref);
- // Ensure compiler can't optimize-out above variables.
- (void)data;
- (void)type;
- (void)size;
- }
-
- // Ensure that short files are detected as corrupt and full files are not.
- EXPECT_EQ(filesize != minsize, allocator.IsCorrupt());
- } else {
- // For filesize >= minsize, the file must be acceptable. This
- // else clause (file-not-acceptable) should be reached only if
- // filesize < minsize.
- EXPECT_LT(filesize, minsize);
- }
-
- strings::SafeSPrintf(filename, "memory_%d_B", filesize);
- file_path = temp_dir.GetPath().AppendASCII(filename);
- ASSERT_FALSE(PathExists(file_path));
- {
- File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE);
- ASSERT_TRUE(writer.IsValid());
- writer.Write(0, (const char*)garbage.get(), filesize);
- }
- ASSERT_TRUE(PathExists(file_path));
-
- mmfile.reset(new MemoryMappedFile());
- mmfile->Initialize(File(file_path, file_flags), map_access);
- EXPECT_EQ(filesize, mmfile->length());
- if (FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, read_only)) {
- // Make sure construction doesn't crash. It will, however, cause
- // error messages warning about about a corrupted memory segment.
- FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, "",
- read_only);
- EXPECT_TRUE(allocator.IsCorrupt()); // Garbage data so it should be.
- } else {
- // For filesize >= minsize, the file must be acceptable. This
- // else clause (file-not-acceptable) should be reached only if
- // filesize < minsize.
- EXPECT_GT(minsize, filesize);
- }
- }
-}
-
-TEST_F(PersistentMemoryAllocatorTest, TruncateTest) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath file_path = temp_dir.GetPath().AppendASCII("truncate_test");
-
- // Start with a small but valid file of persistent data. Keep the "used"
- // amount for both allocations.
- Reference a1_ref;
- Reference a2_ref;
- size_t a1_used;
- size_t a2_used;
- ASSERT_FALSE(PathExists(file_path));
- {
- LocalPersistentMemoryAllocator allocator(TEST_MEMORY_SIZE, TEST_ID, "");
- a1_ref = allocator.Allocate(100 << 10, 1);
- allocator.MakeIterable(a1_ref);
- a1_used = allocator.used();
- a2_ref = allocator.Allocate(200 << 10, 11);
- allocator.MakeIterable(a2_ref);
- a2_used = allocator.used();
-
- File writer(file_path, File::FLAG_CREATE | File::FLAG_WRITE);
- ASSERT_TRUE(writer.IsValid());
- writer.Write(0, static_cast<const char*>(allocator.data()),
- allocator.size());
- }
- ASSERT_TRUE(PathExists(file_path));
- EXPECT_LE(a1_used, a2_ref);
-
- // Truncate the file to include everything and make sure it can be read, both
- // with read-write and read-only access.
- for (size_t file_length : {a2_used, a1_used, a1_used / 2}) {
- SCOPED_TRACE(StringPrintf("file_length=%zu", file_length));
- SetFileLength(file_path, file_length);
-
- for (bool read_only : {false, true}) {
- SCOPED_TRACE(StringPrintf("read_only=%s", read_only ? "true" : "false"));
-
- std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile());
- mmfile->Initialize(
- File(file_path, File::FLAG_OPEN |
- (read_only ? File::FLAG_READ
- : File::FLAG_READ | File::FLAG_WRITE)),
- read_only ? MemoryMappedFile::READ_ONLY
- : MemoryMappedFile::READ_WRITE);
- ASSERT_TRUE(
- FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, read_only));
-
- FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, "",
- read_only);
-
- PersistentMemoryAllocator::Iterator iter(&allocator);
- uint32_t type_id;
- EXPECT_EQ(file_length >= a1_used ? a1_ref : 0U, iter.GetNext(&type_id));
- EXPECT_EQ(file_length >= a2_used ? a2_ref : 0U, iter.GetNext(&type_id));
- EXPECT_EQ(0U, iter.GetNext(&type_id));
-
- // Ensure that short files are detected as corrupt and full files are not.
- EXPECT_EQ(file_length < a2_used, allocator.IsCorrupt());
- }
-
- // Ensure that file length was not adjusted.
- int64_t actual_length;
- ASSERT_TRUE(GetFileSize(file_path, &actual_length));
- EXPECT_EQ(file_length, static_cast<size_t>(actual_length));
- }
-}
-
-#endif // !defined(OS_NACL)
-
-} // namespace base
diff --git a/base/metrics/persistent_sample_map_unittest.cc b/base/metrics/persistent_sample_map_unittest.cc
deleted file mode 100644
index b25f582..0000000
--- a/base/metrics/persistent_sample_map_unittest.cc
+++ /dev/null
@@ -1,260 +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/metrics/persistent_sample_map.h"
-
-#include <memory>
-
-#include "base/memory/ptr_util.h"
-#include "base/metrics/persistent_histogram_allocator.h"
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-std::unique_ptr<PersistentHistogramAllocator> CreateHistogramAllocator(
- size_t bytes) {
- return std::make_unique<PersistentHistogramAllocator>(
- std::make_unique<LocalPersistentMemoryAllocator>(bytes, 0, ""));
-}
-
-std::unique_ptr<PersistentHistogramAllocator> DuplicateHistogramAllocator(
- PersistentHistogramAllocator* original) {
- return std::make_unique<PersistentHistogramAllocator>(
- std::make_unique<PersistentMemoryAllocator>(
- const_cast<void*>(original->data()), original->length(), 0,
- original->Id(), original->Name(), false));
-}
-
-TEST(PersistentSampleMapTest, AccumulateTest) {
- std::unique_ptr<PersistentHistogramAllocator> allocator =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta;
- PersistentSampleMap samples(1, allocator.get(), &meta);
-
- samples.Accumulate(1, 100);
- samples.Accumulate(2, 200);
- samples.Accumulate(1, -200);
- EXPECT_EQ(-100, samples.GetCount(1));
- EXPECT_EQ(200, samples.GetCount(2));
-
- EXPECT_EQ(300, samples.sum());
- EXPECT_EQ(100, samples.TotalCount());
- EXPECT_EQ(samples.redundant_count(), samples.TotalCount());
-}
-
-TEST(PersistentSampleMapTest, Accumulate_LargeValuesDontOverflow) {
- std::unique_ptr<PersistentHistogramAllocator> allocator =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta;
- PersistentSampleMap samples(1, allocator.get(), &meta);
-
- samples.Accumulate(250000000, 100);
- samples.Accumulate(500000000, 200);
- samples.Accumulate(250000000, -200);
- EXPECT_EQ(-100, samples.GetCount(250000000));
- EXPECT_EQ(200, samples.GetCount(500000000));
-
- EXPECT_EQ(75000000000LL, samples.sum());
- EXPECT_EQ(100, samples.TotalCount());
- EXPECT_EQ(samples.redundant_count(), samples.TotalCount());
-}
-
-TEST(PersistentSampleMapTest, AddSubtractTest) {
- std::unique_ptr<PersistentHistogramAllocator> allocator1 =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta1;
- PersistentSampleMap samples1(1, allocator1.get(), &meta1);
- samples1.Accumulate(1, 100);
- samples1.Accumulate(2, 100);
- samples1.Accumulate(3, 100);
-
- std::unique_ptr<PersistentHistogramAllocator> allocator2 =
- DuplicateHistogramAllocator(allocator1.get());
- HistogramSamples::LocalMetadata meta2;
- PersistentSampleMap samples2(2, allocator2.get(), &meta2);
- samples2.Accumulate(1, 200);
- samples2.Accumulate(2, 200);
- samples2.Accumulate(4, 200);
-
- samples1.Add(samples2);
- EXPECT_EQ(300, samples1.GetCount(1));
- EXPECT_EQ(300, samples1.GetCount(2));
- EXPECT_EQ(100, samples1.GetCount(3));
- EXPECT_EQ(200, samples1.GetCount(4));
- EXPECT_EQ(2000, samples1.sum());
- EXPECT_EQ(900, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-
- samples1.Subtract(samples2);
- EXPECT_EQ(100, samples1.GetCount(1));
- EXPECT_EQ(100, samples1.GetCount(2));
- EXPECT_EQ(100, samples1.GetCount(3));
- EXPECT_EQ(0, samples1.GetCount(4));
- EXPECT_EQ(600, samples1.sum());
- EXPECT_EQ(300, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-}
-
-TEST(PersistentSampleMapTest, PersistenceTest) {
- std::unique_ptr<PersistentHistogramAllocator> allocator1 =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta12;
- PersistentSampleMap samples1(12, allocator1.get(), &meta12);
- samples1.Accumulate(1, 100);
- samples1.Accumulate(2, 200);
- samples1.Accumulate(1, -200);
- samples1.Accumulate(-1, 1);
- EXPECT_EQ(-100, samples1.GetCount(1));
- EXPECT_EQ(200, samples1.GetCount(2));
- EXPECT_EQ(1, samples1.GetCount(-1));
- EXPECT_EQ(299, samples1.sum());
- EXPECT_EQ(101, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-
- std::unique_ptr<PersistentHistogramAllocator> allocator2 =
- DuplicateHistogramAllocator(allocator1.get());
- PersistentSampleMap samples2(12, allocator2.get(), &meta12);
- EXPECT_EQ(samples1.id(), samples2.id());
- EXPECT_EQ(samples1.sum(), samples2.sum());
- EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
- EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
- EXPECT_EQ(-100, samples2.GetCount(1));
- EXPECT_EQ(200, samples2.GetCount(2));
- EXPECT_EQ(1, samples2.GetCount(-1));
- EXPECT_EQ(299, samples2.sum());
- EXPECT_EQ(101, samples2.TotalCount());
- EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount());
-
- samples1.Accumulate(-1, -1);
- EXPECT_EQ(0, samples2.GetCount(3));
- EXPECT_EQ(0, samples1.GetCount(3));
- samples2.Accumulate(3, 300);
- EXPECT_EQ(300, samples2.GetCount(3));
- EXPECT_EQ(300, samples1.GetCount(3));
- EXPECT_EQ(samples1.sum(), samples2.sum());
- EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
- EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
-
- EXPECT_EQ(0, samples2.GetCount(4));
- EXPECT_EQ(0, samples1.GetCount(4));
- samples1.Accumulate(4, 400);
- EXPECT_EQ(400, samples2.GetCount(4));
- EXPECT_EQ(400, samples1.GetCount(4));
- samples2.Accumulate(4, 4000);
- EXPECT_EQ(4400, samples2.GetCount(4));
- EXPECT_EQ(4400, samples1.GetCount(4));
- EXPECT_EQ(samples1.sum(), samples2.sum());
- EXPECT_EQ(samples1.redundant_count(), samples2.redundant_count());
- EXPECT_EQ(samples1.TotalCount(), samples2.TotalCount());
-}
-
-TEST(PersistentSampleMapIteratorTest, IterateTest) {
- std::unique_ptr<PersistentHistogramAllocator> allocator =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta;
- PersistentSampleMap samples(1, allocator.get(), &meta);
- samples.Accumulate(1, 100);
- samples.Accumulate(2, 200);
- samples.Accumulate(4, -300);
- samples.Accumulate(5, 0);
-
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
-
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(2, max);
- EXPECT_EQ(100, count);
- EXPECT_FALSE(it->GetBucketIndex(nullptr));
-
- it->Next();
- it->Get(&min, &max, &count);
- EXPECT_EQ(2, min);
- EXPECT_EQ(3, max);
- EXPECT_EQ(200, count);
-
- it->Next();
- it->Get(&min, &max, &count);
- EXPECT_EQ(4, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(-300, count);
-
- it->Next();
- EXPECT_TRUE(it->Done());
-}
-
-TEST(PersistentSampleMapIteratorTest, SkipEmptyRanges) {
- std::unique_ptr<PersistentHistogramAllocator> allocator1 =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta1;
- PersistentSampleMap samples1(1, allocator1.get(), &meta1);
- samples1.Accumulate(5, 1);
- samples1.Accumulate(10, 2);
- samples1.Accumulate(15, 3);
- samples1.Accumulate(20, 4);
- samples1.Accumulate(25, 5);
-
- std::unique_ptr<PersistentHistogramAllocator> allocator2 =
- DuplicateHistogramAllocator(allocator1.get());
- HistogramSamples::LocalMetadata meta2;
- PersistentSampleMap samples2(2, allocator2.get(), &meta2);
- samples2.Accumulate(5, 1);
- samples2.Accumulate(20, 4);
- samples2.Accumulate(25, 5);
-
- samples1.Subtract(samples2);
-
- std::unique_ptr<SampleCountIterator> it = samples1.Iterator();
- EXPECT_FALSE(it->Done());
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
-
- it->Get(&min, &max, &count);
- EXPECT_EQ(10, min);
- EXPECT_EQ(11, max);
- EXPECT_EQ(2, count);
-
- it->Next();
- EXPECT_FALSE(it->Done());
-
- it->Get(&min, &max, &count);
- EXPECT_EQ(15, min);
- EXPECT_EQ(16, max);
- EXPECT_EQ(3, count);
-
- it->Next();
- EXPECT_TRUE(it->Done());
-}
-
-TEST(PersistentSampleMapIteratorDeathTest, IterateDoneTest) {
- std::unique_ptr<PersistentHistogramAllocator> allocator =
- CreateHistogramAllocator(64 << 10); // 64 KiB
- HistogramSamples::LocalMetadata meta;
- PersistentSampleMap samples(1, allocator.get(), &meta);
-
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
-
- EXPECT_TRUE(it->Done());
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count));
-
- EXPECT_DCHECK_DEATH(it->Next());
-
- samples.Accumulate(1, 100);
- it = samples.Iterator();
- EXPECT_FALSE(it->Done());
-}
-
-} // namespace
-} // namespace base
diff --git a/base/metrics/sample_map_unittest.cc b/base/metrics/sample_map_unittest.cc
deleted file mode 100644
index 83db56f..0000000
--- a/base/metrics/sample_map_unittest.cc
+++ /dev/null
@@ -1,168 +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/metrics/sample_map.h"
-
-#include <memory>
-
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-TEST(SampleMapTest, AccumulateTest) {
- SampleMap samples(1);
-
- samples.Accumulate(1, 100);
- samples.Accumulate(2, 200);
- samples.Accumulate(1, -200);
- EXPECT_EQ(-100, samples.GetCount(1));
- EXPECT_EQ(200, samples.GetCount(2));
-
- EXPECT_EQ(300, samples.sum());
- EXPECT_EQ(100, samples.TotalCount());
- EXPECT_EQ(samples.redundant_count(), samples.TotalCount());
-}
-
-TEST(SampleMapTest, Accumulate_LargeValuesDontOverflow) {
- SampleMap samples(1);
-
- samples.Accumulate(250000000, 100);
- samples.Accumulate(500000000, 200);
- samples.Accumulate(250000000, -200);
- EXPECT_EQ(-100, samples.GetCount(250000000));
- EXPECT_EQ(200, samples.GetCount(500000000));
-
- EXPECT_EQ(75000000000LL, samples.sum());
- EXPECT_EQ(100, samples.TotalCount());
- EXPECT_EQ(samples.redundant_count(), samples.TotalCount());
-}
-
-TEST(SampleMapTest, AddSubtractTest) {
- SampleMap samples1(1);
- SampleMap samples2(2);
-
- samples1.Accumulate(1, 100);
- samples1.Accumulate(2, 100);
- samples1.Accumulate(3, 100);
-
- samples2.Accumulate(1, 200);
- samples2.Accumulate(2, 200);
- samples2.Accumulate(4, 200);
-
- samples1.Add(samples2);
- EXPECT_EQ(300, samples1.GetCount(1));
- EXPECT_EQ(300, samples1.GetCount(2));
- EXPECT_EQ(100, samples1.GetCount(3));
- EXPECT_EQ(200, samples1.GetCount(4));
- EXPECT_EQ(2000, samples1.sum());
- EXPECT_EQ(900, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-
- samples1.Subtract(samples2);
- EXPECT_EQ(100, samples1.GetCount(1));
- EXPECT_EQ(100, samples1.GetCount(2));
- EXPECT_EQ(100, samples1.GetCount(3));
- EXPECT_EQ(0, samples1.GetCount(4));
- EXPECT_EQ(600, samples1.sum());
- EXPECT_EQ(300, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-}
-
-TEST(SampleMapIteratorTest, IterateTest) {
- SampleMap samples(1);
- samples.Accumulate(1, 100);
- samples.Accumulate(2, 200);
- samples.Accumulate(4, -300);
- samples.Accumulate(5, 0);
-
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
-
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(2, max);
- EXPECT_EQ(100, count);
- EXPECT_FALSE(it->GetBucketIndex(nullptr));
-
- it->Next();
- it->Get(&min, &max, &count);
- EXPECT_EQ(2, min);
- EXPECT_EQ(3, max);
- EXPECT_EQ(200, count);
-
- it->Next();
- it->Get(&min, &max, &count);
- EXPECT_EQ(4, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(-300, count);
-
- it->Next();
- EXPECT_TRUE(it->Done());
-}
-
-TEST(SampleMapIteratorTest, SkipEmptyRanges) {
- SampleMap samples(1);
- samples.Accumulate(5, 1);
- samples.Accumulate(10, 2);
- samples.Accumulate(15, 3);
- samples.Accumulate(20, 4);
- samples.Accumulate(25, 5);
-
- SampleMap samples2(2);
- samples2.Accumulate(5, 1);
- samples2.Accumulate(20, 4);
- samples2.Accumulate(25, 5);
-
- samples.Subtract(samples2);
-
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
- EXPECT_FALSE(it->Done());
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
-
- it->Get(&min, &max, &count);
- EXPECT_EQ(10, min);
- EXPECT_EQ(11, max);
- EXPECT_EQ(2, count);
-
- it->Next();
- EXPECT_FALSE(it->Done());
-
- it->Get(&min, &max, &count);
- EXPECT_EQ(15, min);
- EXPECT_EQ(16, max);
- EXPECT_EQ(3, count);
-
- it->Next();
- EXPECT_TRUE(it->Done());
-}
-
-TEST(SampleMapIteratorDeathTest, IterateDoneTest) {
- SampleMap samples(1);
-
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
-
- EXPECT_TRUE(it->Done());
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count));
-
- EXPECT_DCHECK_DEATH(it->Next());
-
- samples.Accumulate(1, 100);
- it = samples.Iterator();
- EXPECT_FALSE(it->Done());
-}
-
-} // namespace
-} // namespace base
diff --git a/base/metrics/sample_vector_unittest.cc b/base/metrics/sample_vector_unittest.cc
deleted file mode 100644
index 4921802..0000000
--- a/base/metrics/sample_vector_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 "base/metrics/sample_vector.h"
-
-#include <limits.h>
-#include <stddef.h>
-
-#include <atomic>
-#include <memory>
-#include <vector>
-
-#include "base/metrics/bucket_ranges.h"
-#include "base/metrics/histogram.h"
-#include "base/metrics/persistent_memory_allocator.h"
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// This framework class has "friend" access to the SampleVector for accessing
-// non-public methods and fields.
-class SampleVectorTest : public testing::Test {
- public:
- const HistogramBase::AtomicCount* GetSamplesCounts(
- const SampleVectorBase& samples) {
- return samples.counts();
- }
-};
-
-TEST_F(SampleVectorTest, Accumulate) {
- // Custom buckets: [1, 5) [5, 10)
- BucketRanges ranges(3);
- ranges.set_range(0, 1);
- ranges.set_range(1, 5);
- ranges.set_range(2, 10);
- SampleVector samples(1, &ranges);
-
- samples.Accumulate(1, 200);
- samples.Accumulate(2, -300);
- EXPECT_EQ(-100, samples.GetCountAtIndex(0));
-
- samples.Accumulate(5, 200);
- EXPECT_EQ(200, samples.GetCountAtIndex(1));
-
- EXPECT_EQ(600, samples.sum());
- EXPECT_EQ(100, samples.redundant_count());
- EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
-
- samples.Accumulate(5, -100);
- EXPECT_EQ(100, samples.GetCountAtIndex(1));
-
- EXPECT_EQ(100, samples.sum());
- EXPECT_EQ(0, samples.redundant_count());
- EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
-}
-
-TEST_F(SampleVectorTest, Accumulate_LargeValuesDontOverflow) {
- // Custom buckets: [1, 250000000) [250000000, 500000000)
- BucketRanges ranges(3);
- ranges.set_range(0, 1);
- ranges.set_range(1, 250000000);
- ranges.set_range(2, 500000000);
- SampleVector samples(1, &ranges);
-
- samples.Accumulate(240000000, 200);
- samples.Accumulate(249999999, -300);
- EXPECT_EQ(-100, samples.GetCountAtIndex(0));
-
- samples.Accumulate(250000000, 200);
- EXPECT_EQ(200, samples.GetCountAtIndex(1));
-
- EXPECT_EQ(23000000300LL, samples.sum());
- EXPECT_EQ(100, samples.redundant_count());
- EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
-
- samples.Accumulate(250000000, -100);
- EXPECT_EQ(100, samples.GetCountAtIndex(1));
-
- EXPECT_EQ(-1999999700LL, samples.sum());
- EXPECT_EQ(0, samples.redundant_count());
- EXPECT_EQ(samples.TotalCount(), samples.redundant_count());
-}
-
-TEST_F(SampleVectorTest, AddSubtract) {
- // Custom buckets: [0, 1) [1, 2) [2, 3) [3, INT_MAX)
- BucketRanges ranges(5);
- ranges.set_range(0, 0);
- ranges.set_range(1, 1);
- ranges.set_range(2, 2);
- ranges.set_range(3, 3);
- ranges.set_range(4, INT_MAX);
-
- SampleVector samples1(1, &ranges);
- samples1.Accumulate(0, 100);
- samples1.Accumulate(2, 100);
- samples1.Accumulate(4, 100);
- EXPECT_EQ(600, samples1.sum());
- EXPECT_EQ(300, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-
- SampleVector samples2(2, &ranges);
- samples2.Accumulate(1, 200);
- samples2.Accumulate(2, 200);
- samples2.Accumulate(4, 200);
- EXPECT_EQ(1400, samples2.sum());
- EXPECT_EQ(600, samples2.TotalCount());
- EXPECT_EQ(samples2.redundant_count(), samples2.TotalCount());
-
- samples1.Add(samples2);
- EXPECT_EQ(100, samples1.GetCountAtIndex(0));
- EXPECT_EQ(200, samples1.GetCountAtIndex(1));
- EXPECT_EQ(300, samples1.GetCountAtIndex(2));
- EXPECT_EQ(300, samples1.GetCountAtIndex(3));
- EXPECT_EQ(2000, samples1.sum());
- EXPECT_EQ(900, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-
- samples1.Subtract(samples2);
- EXPECT_EQ(100, samples1.GetCountAtIndex(0));
- EXPECT_EQ(0, samples1.GetCountAtIndex(1));
- EXPECT_EQ(100, samples1.GetCountAtIndex(2));
- EXPECT_EQ(100, samples1.GetCountAtIndex(3));
- EXPECT_EQ(600, samples1.sum());
- EXPECT_EQ(300, samples1.TotalCount());
- EXPECT_EQ(samples1.redundant_count(), samples1.TotalCount());
-}
-
-TEST_F(SampleVectorTest, BucketIndexDeath) {
- // 8 buckets with exponential layout:
- // [0, 1) [1, 2) [2, 4) [4, 8) [8, 16) [16, 32) [32, 64) [64, INT_MAX)
- BucketRanges ranges(9);
- Histogram::InitializeBucketRanges(1, 64, &ranges);
- SampleVector samples(1, &ranges);
-
- // Normal case
- samples.Accumulate(0, 1);
- samples.Accumulate(3, 2);
- samples.Accumulate(64, 3);
- EXPECT_EQ(1, samples.GetCount(0));
- EXPECT_EQ(2, samples.GetCount(2));
- EXPECT_EQ(3, samples.GetCount(65));
-
- // Extreme case.
- EXPECT_DEATH_IF_SUPPORTED(samples.Accumulate(INT_MIN, 100), "");
- EXPECT_DEATH_IF_SUPPORTED(samples.Accumulate(-1, 100), "");
- EXPECT_DEATH_IF_SUPPORTED(samples.Accumulate(INT_MAX, 100), "");
-
- // Custom buckets: [1, 5) [5, 10)
- // Note, this is not a valid BucketRanges for Histogram because it does not
- // have overflow buckets.
- BucketRanges ranges2(3);
- ranges2.set_range(0, 1);
- ranges2.set_range(1, 5);
- ranges2.set_range(2, 10);
- SampleVector samples2(2, &ranges2);
-
- // Normal case.
- samples2.Accumulate(1, 1);
- samples2.Accumulate(4, 1);
- samples2.Accumulate(5, 2);
- samples2.Accumulate(9, 2);
- EXPECT_EQ(2, samples2.GetCount(1));
- EXPECT_EQ(4, samples2.GetCount(5));
-
- // Extreme case.
- EXPECT_DEATH_IF_SUPPORTED(samples2.Accumulate(0, 100), "");
- EXPECT_DEATH_IF_SUPPORTED(samples2.Accumulate(10, 100), "");
-}
-
-TEST_F(SampleVectorTest, AddSubtractBucketNotMatchDeath) {
- // Custom buckets 1: [1, 3) [3, 5)
- BucketRanges ranges1(3);
- ranges1.set_range(0, 1);
- ranges1.set_range(1, 3);
- ranges1.set_range(2, 5);
- SampleVector samples1(1, &ranges1);
-
- // Custom buckets 2: [0, 1) [1, 3) [3, 6) [6, 7)
- BucketRanges ranges2(5);
- ranges2.set_range(0, 0);
- ranges2.set_range(1, 1);
- ranges2.set_range(2, 3);
- ranges2.set_range(3, 6);
- ranges2.set_range(4, 7);
- SampleVector samples2(2, &ranges2);
-
- samples2.Accumulate(1, 100);
- samples1.Add(samples2);
- EXPECT_EQ(100, samples1.GetCountAtIndex(0));
-
- // Extra bucket in the beginning. These should CHECK in GetBucketIndex.
- samples2.Accumulate(0, 100);
- EXPECT_DEATH_IF_SUPPORTED(samples1.Add(samples2), "");
- EXPECT_DEATH_IF_SUPPORTED(samples1.Subtract(samples2), "");
-
- // Extra bucket in the end. These should cause AddSubtractImpl to fail, and
- // Add to DCHECK as a result.
- samples2.Accumulate(0, -100);
- samples2.Accumulate(6, 100);
- EXPECT_DCHECK_DEATH(samples1.Add(samples2));
- EXPECT_DCHECK_DEATH(samples1.Subtract(samples2));
-
- // Bucket not match: [3, 5) VS [3, 6). These should cause AddSubtractImpl to
- // DCHECK.
- samples2.Accumulate(6, -100);
- samples2.Accumulate(3, 100);
- EXPECT_DCHECK_DEATH(samples1.Add(samples2));
- EXPECT_DCHECK_DEATH(samples1.Subtract(samples2));
-}
-
-TEST_F(SampleVectorTest, Iterate) {
- BucketRanges ranges(5);
- ranges.set_range(0, 0);
- ranges.set_range(1, 1);
- ranges.set_range(2, 2);
- ranges.set_range(3, 3);
- ranges.set_range(4, 4);
-
- std::vector<HistogramBase::Count> counts(3);
- counts[0] = 1;
- counts[1] = 0; // Iterator will bypass this empty bucket.
- counts[2] = 2;
-
- // BucketRanges can have larger size than counts.
- SampleVectorIterator it(&counts, &ranges);
- size_t index;
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- it.Get(&min, &max, &count);
- EXPECT_EQ(0, min);
- EXPECT_EQ(1, max);
- EXPECT_EQ(1, count);
- EXPECT_TRUE(it.GetBucketIndex(&index));
- EXPECT_EQ(0u, index);
-
- it.Next();
- it.Get(&min, &max, &count);
- EXPECT_EQ(2, min);
- EXPECT_EQ(3, max);
- EXPECT_EQ(2, count);
- EXPECT_TRUE(it.GetBucketIndex(&index));
- EXPECT_EQ(2u, index);
-
- it.Next();
- EXPECT_TRUE(it.Done());
-
- // Create iterator from SampleVector.
- SampleVector samples(1, &ranges);
- samples.Accumulate(0, 0);
- samples.Accumulate(1, 1);
- samples.Accumulate(2, 2);
- samples.Accumulate(3, 3);
- std::unique_ptr<SampleCountIterator> it2 = samples.Iterator();
-
- int i;
- for (i = 1; !it2->Done(); i++, it2->Next()) {
- it2->Get(&min, &max, &count);
- EXPECT_EQ(i, min);
- EXPECT_EQ(i + 1, max);
- EXPECT_EQ(i, count);
-
- size_t index;
- EXPECT_TRUE(it2->GetBucketIndex(&index));
- EXPECT_EQ(static_cast<size_t>(i), index);
- }
- EXPECT_EQ(4, i);
-}
-
-TEST_F(SampleVectorTest, IterateDoneDeath) {
- BucketRanges ranges(5);
- ranges.set_range(0, 0);
- ranges.set_range(1, 1);
- ranges.set_range(2, 2);
- ranges.set_range(3, 3);
- ranges.set_range(4, INT_MAX);
- SampleVector samples(1, &ranges);
-
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
-
- EXPECT_TRUE(it->Done());
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- EXPECT_DCHECK_DEATH(it->Get(&min, &max, &count));
-
- EXPECT_DCHECK_DEATH(it->Next());
-
- samples.Accumulate(2, 100);
- it = samples.Iterator();
- EXPECT_FALSE(it->Done());
-}
-
-TEST_F(SampleVectorTest, SingleSample) {
- // Custom buckets: [1, 5) [5, 10)
- BucketRanges ranges(3);
- ranges.set_range(0, 1);
- ranges.set_range(1, 5);
- ranges.set_range(2, 10);
- SampleVector samples(&ranges);
-
- // Ensure that a single value accumulates correctly.
- EXPECT_FALSE(GetSamplesCounts(samples));
- samples.Accumulate(3, 200);
- EXPECT_EQ(200, samples.GetCount(3));
- EXPECT_FALSE(GetSamplesCounts(samples));
- samples.Accumulate(3, 400);
- EXPECT_EQ(600, samples.GetCount(3));
- EXPECT_FALSE(GetSamplesCounts(samples));
- EXPECT_EQ(3 * 600, samples.sum());
- EXPECT_EQ(600, samples.TotalCount());
- EXPECT_EQ(600, samples.redundant_count());
-
- // Ensure that the iterator returns only one value.
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- std::unique_ptr<SampleCountIterator> it = samples.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(600, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-
- // Ensure that it can be merged to another single-sample vector.
- SampleVector samples_copy(&ranges);
- samples_copy.Add(samples);
- EXPECT_FALSE(GetSamplesCounts(samples_copy));
- EXPECT_EQ(3 * 600, samples_copy.sum());
- EXPECT_EQ(600, samples_copy.TotalCount());
- EXPECT_EQ(600, samples_copy.redundant_count());
-
- // A different value should cause creation of the counts array.
- samples.Accumulate(8, 100);
- EXPECT_TRUE(GetSamplesCounts(samples));
- EXPECT_EQ(600, samples.GetCount(3));
- EXPECT_EQ(100, samples.GetCount(8));
- EXPECT_EQ(3 * 600 + 8 * 100, samples.sum());
- EXPECT_EQ(600 + 100, samples.TotalCount());
- EXPECT_EQ(600 + 100, samples.redundant_count());
-
- // The iterator should now return both values.
- it = samples.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(600, count);
- it->Next();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(5, min);
- EXPECT_EQ(10, max);
- EXPECT_EQ(100, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-
- // Ensure that it can merged to a single-sample vector.
- samples_copy.Add(samples);
- EXPECT_TRUE(GetSamplesCounts(samples_copy));
- EXPECT_EQ(3 * 1200 + 8 * 100, samples_copy.sum());
- EXPECT_EQ(1200 + 100, samples_copy.TotalCount());
- EXPECT_EQ(1200 + 100, samples_copy.redundant_count());
-}
-
-TEST_F(SampleVectorTest, PersistentSampleVector) {
- LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");
- std::atomic<PersistentMemoryAllocator::Reference> samples_ref;
- samples_ref.store(0, std::memory_order_relaxed);
- HistogramSamples::Metadata samples_meta;
- memset(&samples_meta, 0, sizeof(samples_meta));
-
- // Custom buckets: [1, 5) [5, 10)
- BucketRanges ranges(3);
- ranges.set_range(0, 1);
- ranges.set_range(1, 5);
- ranges.set_range(2, 10);
-
- // Persistent allocation.
- const size_t counts_bytes =
- sizeof(HistogramBase::AtomicCount) * ranges.bucket_count();
- const DelayedPersistentAllocation allocation(&allocator, &samples_ref, 1,
- counts_bytes, false);
-
- PersistentSampleVector samples1(0, &ranges, &samples_meta, allocation);
- EXPECT_FALSE(GetSamplesCounts(samples1));
- samples1.Accumulate(3, 200);
- EXPECT_EQ(200, samples1.GetCount(3));
- EXPECT_FALSE(GetSamplesCounts(samples1));
- EXPECT_EQ(0, samples1.GetCount(8));
- EXPECT_FALSE(GetSamplesCounts(samples1));
-
- PersistentSampleVector samples2(0, &ranges, &samples_meta, allocation);
- EXPECT_EQ(200, samples2.GetCount(3));
- EXPECT_FALSE(GetSamplesCounts(samples2));
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- std::unique_ptr<SampleCountIterator> it = samples2.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(200, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-
- samples1.Accumulate(8, 100);
- EXPECT_TRUE(GetSamplesCounts(samples1));
-
- EXPECT_FALSE(GetSamplesCounts(samples2));
- EXPECT_EQ(200, samples2.GetCount(3));
- EXPECT_EQ(100, samples2.GetCount(8));
- EXPECT_TRUE(GetSamplesCounts(samples2));
- EXPECT_EQ(3 * 200 + 8 * 100, samples2.sum());
- EXPECT_EQ(300, samples2.TotalCount());
- EXPECT_EQ(300, samples2.redundant_count());
-
- it = samples2.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(200, count);
- it->Next();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(5, min);
- EXPECT_EQ(10, max);
- EXPECT_EQ(100, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-
- PersistentSampleVector samples3(0, &ranges, &samples_meta, allocation);
- EXPECT_TRUE(GetSamplesCounts(samples2));
- EXPECT_EQ(200, samples3.GetCount(3));
- EXPECT_EQ(100, samples3.GetCount(8));
- EXPECT_EQ(3 * 200 + 8 * 100, samples3.sum());
- EXPECT_EQ(300, samples3.TotalCount());
- EXPECT_EQ(300, samples3.redundant_count());
-
- it = samples3.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(200, count);
- it->Next();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(5, min);
- EXPECT_EQ(10, max);
- EXPECT_EQ(100, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-}
-
-TEST_F(SampleVectorTest, PersistentSampleVectorTestWithOutsideAlloc) {
- LocalPersistentMemoryAllocator allocator(64 << 10, 0, "");
- std::atomic<PersistentMemoryAllocator::Reference> samples_ref;
- samples_ref.store(0, std::memory_order_relaxed);
- HistogramSamples::Metadata samples_meta;
- memset(&samples_meta, 0, sizeof(samples_meta));
-
- // Custom buckets: [1, 5) [5, 10)
- BucketRanges ranges(3);
- ranges.set_range(0, 1);
- ranges.set_range(1, 5);
- ranges.set_range(2, 10);
-
- // Persistent allocation.
- const size_t counts_bytes =
- sizeof(HistogramBase::AtomicCount) * ranges.bucket_count();
- const DelayedPersistentAllocation allocation(&allocator, &samples_ref, 1,
- counts_bytes, false);
-
- PersistentSampleVector samples1(0, &ranges, &samples_meta, allocation);
- EXPECT_FALSE(GetSamplesCounts(samples1));
- samples1.Accumulate(3, 200);
- EXPECT_EQ(200, samples1.GetCount(3));
- EXPECT_FALSE(GetSamplesCounts(samples1));
-
- // Because the delayed allocation can be shared with other objects (the
- // |offset| parameter allows concatinating multiple data blocks into the
- // same allocation), it's possible that the allocation gets realized from
- // the outside even though the data block being accessed is all zero.
- allocation.Get();
- EXPECT_EQ(200, samples1.GetCount(3));
- EXPECT_FALSE(GetSamplesCounts(samples1));
-
- HistogramBase::Sample min;
- int64_t max;
- HistogramBase::Count count;
- std::unique_ptr<SampleCountIterator> it = samples1.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(200, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-
- // A duplicate samples object should still see the single-sample entry even
- // when storage is available.
- PersistentSampleVector samples2(0, &ranges, &samples_meta, allocation);
- EXPECT_EQ(200, samples2.GetCount(3));
-
- // New accumulations, in both directions, of the existing value should work.
- samples1.Accumulate(3, 50);
- EXPECT_EQ(250, samples1.GetCount(3));
- EXPECT_EQ(250, samples2.GetCount(3));
- samples2.Accumulate(3, 50);
- EXPECT_EQ(300, samples1.GetCount(3));
- EXPECT_EQ(300, samples2.GetCount(3));
-
- it = samples1.Iterator();
- ASSERT_FALSE(it->Done());
- it->Get(&min, &max, &count);
- EXPECT_EQ(1, min);
- EXPECT_EQ(5, max);
- EXPECT_EQ(300, count);
- it->Next();
- EXPECT_TRUE(it->Done());
-
- samples1.Accumulate(8, 100);
- EXPECT_TRUE(GetSamplesCounts(samples1));
- EXPECT_EQ(300, samples1.GetCount(3));
- EXPECT_EQ(300, samples2.GetCount(3));
- EXPECT_EQ(100, samples1.GetCount(8));
- EXPECT_EQ(100, samples2.GetCount(8));
- samples2.Accumulate(8, 100);
- EXPECT_EQ(300, samples1.GetCount(3));
- EXPECT_EQ(300, samples2.GetCount(3));
- EXPECT_EQ(200, samples1.GetCount(8));
- EXPECT_EQ(200, samples2.GetCount(8));
-}
-
-} // namespace base
diff --git a/base/metrics/single_sample_metrics_unittest.cc b/base/metrics/single_sample_metrics_unittest.cc
deleted file mode 100644
index 5a6d159..0000000
--- a/base/metrics/single_sample_metrics_unittest.cc
+++ /dev/null
@@ -1,124 +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/single_sample_metrics.h"
-
-#include "base/memory/ptr_util.h"
-#include "base/metrics/dummy_histogram.h"
-#include "base/test/gtest_util.h"
-#include "base/test/histogram_tester.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-const HistogramBase::Sample kMin = 1;
-const HistogramBase::Sample kMax = 10;
-const uint32_t kBucketCount = 10;
-const char kMetricName[] = "Single.Sample.Metric";
-
-class SingleSampleMetricsTest : public testing::Test {
- public:
- SingleSampleMetricsTest() = default;
-
- ~SingleSampleMetricsTest() override {
- // Ensure we cleanup after ourselves.
- SingleSampleMetricsFactory::DeleteFactoryForTesting();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SingleSampleMetricsTest);
-};
-
-} // namespace
-
-TEST_F(SingleSampleMetricsTest, DefaultFactoryGetSet) {
- SingleSampleMetricsFactory* factory = SingleSampleMetricsFactory::Get();
- ASSERT_TRUE(factory);
-
- // Same factory should be returned evermore.
- EXPECT_EQ(factory, SingleSampleMetricsFactory::Get());
-
- // Setting a factory after the default has been instantiated should fail.
- EXPECT_DCHECK_DEATH(SingleSampleMetricsFactory::SetFactory(
- WrapUnique<SingleSampleMetricsFactory>(nullptr)));
-}
-
-TEST_F(SingleSampleMetricsTest, CustomFactoryGetSet) {
- SingleSampleMetricsFactory* factory = new DefaultSingleSampleMetricsFactory();
- SingleSampleMetricsFactory::SetFactory(WrapUnique(factory));
- EXPECT_EQ(factory, SingleSampleMetricsFactory::Get());
-}
-
-TEST_F(SingleSampleMetricsTest, DefaultSingleSampleMetricNoValue) {
- SingleSampleMetricsFactory* factory = SingleSampleMetricsFactory::Get();
-
- HistogramTester tester;
- std::unique_ptr<SingleSampleMetric> metric =
- factory->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
- metric.reset();
-
- // Verify that no sample is recorded if SetSample() is never called.
- tester.ExpectTotalCount(kMetricName, 0);
-}
-
-TEST_F(SingleSampleMetricsTest, DefaultSingleSampleMetricWithValue) {
- SingleSampleMetricsFactory* factory = SingleSampleMetricsFactory::Get();
-
- HistogramTester tester;
- std::unique_ptr<SingleSampleMetric> metric =
- factory->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
-
- const HistogramBase::Sample kLastSample = 9;
- metric->SetSample(1);
- metric->SetSample(3);
- metric->SetSample(5);
- metric->SetSample(kLastSample);
- metric.reset();
-
- // Verify only the last sample sent to SetSample() is recorded.
- tester.ExpectUniqueSample(kMetricName, kLastSample, 1);
-
- // Verify construction implicitly by requesting a histogram with the same
- // parameters; this test relies on the fact that histogram objects are unique
- // per name. Different parameters will result in a Dummy histogram returned.
- EXPECT_EQ(
- DummyHistogram::GetInstance(),
- Histogram::FactoryGet(kMetricName, 1, 3, 3, HistogramBase::kNoFlags));
- EXPECT_NE(DummyHistogram::GetInstance(),
- Histogram::FactoryGet(kMetricName, kMin, kMax, kBucketCount,
- HistogramBase::kUmaTargetedHistogramFlag));
-}
-
-TEST_F(SingleSampleMetricsTest, MultipleMetricsAreDistinct) {
- SingleSampleMetricsFactory* factory = SingleSampleMetricsFactory::Get();
-
- HistogramTester tester;
- std::unique_ptr<SingleSampleMetric> metric =
- factory->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
- std::unique_ptr<SingleSampleMetric> metric2 =
- factory->CreateCustomCountsMetric(kMetricName, kMin, kMax, kBucketCount);
- const char kMetricName2[] = "Single.Sample.Metric.2";
- std::unique_ptr<SingleSampleMetric> metric3 =
- factory->CreateCustomCountsMetric(kMetricName2, kMin, kMax, kBucketCount);
-
- const HistogramBase::Sample kSample1 = 5;
- metric->SetSample(kSample1);
- metric2->SetSample(kSample1);
-
- const HistogramBase::Sample kSample2 = 7;
- metric3->SetSample(kSample2);
-
- metric.reset();
- tester.ExpectUniqueSample(kMetricName, kSample1, 1);
-
- metric2.reset();
- tester.ExpectUniqueSample(kMetricName, kSample1, 2);
-
- metric3.reset();
- tester.ExpectUniqueSample(kMetricName2, kSample2, 1);
-}
-
-} // namespace base
diff --git a/base/metrics/sparse_histogram_unittest.cc b/base/metrics/sparse_histogram_unittest.cc
deleted file mode 100644
index 72dd905..0000000
--- a/base/metrics/sparse_histogram_unittest.cc
+++ /dev/null
@@ -1,388 +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/metrics/sparse_histogram.h"
-
-#include <memory>
-#include <string>
-
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_functions.h"
-#include "base/metrics/histogram_samples.h"
-#include "base/metrics/metrics_hashes.h"
-#include "base/metrics/persistent_histogram_allocator.h"
-#include "base/metrics/persistent_memory_allocator.h"
-#include "base/metrics/sample_map.h"
-#include "base/metrics/statistics_recorder.h"
-#include "base/pickle.h"
-#include "base/strings/stringprintf.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// Test parameter indicates if a persistent memory allocator should be used
-// for histogram allocation. False will allocate histograms from the process
-// heap.
-class SparseHistogramTest : public testing::TestWithParam<bool> {
- protected:
- const int32_t kAllocatorMemorySize = 8 << 20; // 8 MiB
-
- SparseHistogramTest() : use_persistent_histogram_allocator_(GetParam()) {}
-
- void SetUp() override {
- if (use_persistent_histogram_allocator_)
- CreatePersistentMemoryAllocator();
-
- // Each test will have a clean state (no Histogram / BucketRanges
- // registered).
- InitializeStatisticsRecorder();
- }
-
- void TearDown() override {
- if (allocator_) {
- ASSERT_FALSE(allocator_->IsFull());
- ASSERT_FALSE(allocator_->IsCorrupt());
- }
- UninitializeStatisticsRecorder();
- DestroyPersistentMemoryAllocator();
- }
-
- void InitializeStatisticsRecorder() {
- DCHECK(!statistics_recorder_);
- statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
- }
-
- void UninitializeStatisticsRecorder() {
- statistics_recorder_.reset();
- }
-
- void CreatePersistentMemoryAllocator() {
- GlobalHistogramAllocator::CreateWithLocalMemory(
- kAllocatorMemorySize, 0, "SparseHistogramAllocatorTest");
- allocator_ = GlobalHistogramAllocator::Get()->memory_allocator();
- }
-
- void DestroyPersistentMemoryAllocator() {
- allocator_ = nullptr;
- GlobalHistogramAllocator::ReleaseForTesting();
- }
-
- std::unique_ptr<SparseHistogram> NewSparseHistogram(const char* name) {
- // std::make_unique can't access protected ctor so do it manually. This
- // test class is a friend so can access it.
- return std::unique_ptr<SparseHistogram>(new SparseHistogram(name));
- }
-
- const bool use_persistent_histogram_allocator_;
-
- std::unique_ptr<StatisticsRecorder> statistics_recorder_;
- PersistentMemoryAllocator* allocator_ = nullptr;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SparseHistogramTest);
-};
-
-// Run all HistogramTest cases with both heap and persistent memory.
-INSTANTIATE_TEST_CASE_P(HeapAndPersistent,
- SparseHistogramTest,
- testing::Bool());
-
-
-TEST_P(SparseHistogramTest, BasicTest) {
- std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
- std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
- EXPECT_EQ(0, snapshot->TotalCount());
- EXPECT_EQ(0, snapshot->sum());
-
- histogram->Add(100);
- std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
- EXPECT_EQ(1, snapshot1->TotalCount());
- EXPECT_EQ(1, snapshot1->GetCount(100));
-
- histogram->Add(100);
- histogram->Add(101);
- std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
- EXPECT_EQ(3, snapshot2->TotalCount());
- EXPECT_EQ(2, snapshot2->GetCount(100));
- EXPECT_EQ(1, snapshot2->GetCount(101));
-}
-
-TEST_P(SparseHistogramTest, BasicTestAddCount) {
- std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
- std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
- EXPECT_EQ(0, snapshot->TotalCount());
- EXPECT_EQ(0, snapshot->sum());
-
- histogram->AddCount(100, 15);
- std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
- EXPECT_EQ(15, snapshot1->TotalCount());
- EXPECT_EQ(15, snapshot1->GetCount(100));
-
- histogram->AddCount(100, 15);
- histogram->AddCount(101, 25);
- std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
- EXPECT_EQ(55, snapshot2->TotalCount());
- EXPECT_EQ(30, snapshot2->GetCount(100));
- EXPECT_EQ(25, snapshot2->GetCount(101));
-}
-
-TEST_P(SparseHistogramTest, AddCount_LargeValuesDontOverflow) {
- std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
- std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
- EXPECT_EQ(0, snapshot->TotalCount());
- EXPECT_EQ(0, snapshot->sum());
-
- histogram->AddCount(1000000000, 15);
- std::unique_ptr<HistogramSamples> snapshot1(histogram->SnapshotSamples());
- EXPECT_EQ(15, snapshot1->TotalCount());
- EXPECT_EQ(15, snapshot1->GetCount(1000000000));
-
- histogram->AddCount(1000000000, 15);
- histogram->AddCount(1010000000, 25);
- std::unique_ptr<HistogramSamples> snapshot2(histogram->SnapshotSamples());
- EXPECT_EQ(55, snapshot2->TotalCount());
- EXPECT_EQ(30, snapshot2->GetCount(1000000000));
- EXPECT_EQ(25, snapshot2->GetCount(1010000000));
- EXPECT_EQ(55250000000LL, snapshot2->sum());
-}
-
-// Make sure that counts returned by Histogram::SnapshotDelta do not overflow
-// even when a total count (returned by Histogram::SnapshotSample) does.
-TEST_P(SparseHistogramTest, AddCount_LargeCountsDontOverflow) {
- std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
- std::unique_ptr<HistogramSamples> snapshot(histogram->SnapshotSamples());
- EXPECT_EQ(0, snapshot->TotalCount());
- EXPECT_EQ(0, snapshot->sum());
-
- const int count = (1 << 30) - 1;
-
- // Repeat N times to make sure that there is no internal value overflow.
- for (int i = 0; i < 10; ++i) {
- histogram->AddCount(42, count);
- std::unique_ptr<HistogramSamples> samples = histogram->SnapshotDelta();
- EXPECT_EQ(count, samples->TotalCount());
- EXPECT_EQ(count, samples->GetCount(42));
- }
-}
-
-TEST_P(SparseHistogramTest, MacroBasicTest) {
- UmaHistogramSparse("Sparse", 100);
- UmaHistogramSparse("Sparse", 200);
- UmaHistogramSparse("Sparse", 100);
-
- const StatisticsRecorder::Histograms histograms =
- StatisticsRecorder::GetHistograms();
-
- ASSERT_THAT(histograms, testing::SizeIs(1));
- const HistogramBase* const sparse_histogram = histograms[0];
-
- EXPECT_EQ(SPARSE_HISTOGRAM, sparse_histogram->GetHistogramType());
- EXPECT_EQ("Sparse", StringPiece(sparse_histogram->histogram_name()));
- EXPECT_EQ(
- HistogramBase::kUmaTargetedHistogramFlag |
- (use_persistent_histogram_allocator_ ? HistogramBase::kIsPersistent
- : 0),
- sparse_histogram->flags());
-
- std::unique_ptr<HistogramSamples> samples =
- sparse_histogram->SnapshotSamples();
- EXPECT_EQ(3, samples->TotalCount());
- EXPECT_EQ(2, samples->GetCount(100));
- EXPECT_EQ(1, samples->GetCount(200));
-}
-
-TEST_P(SparseHistogramTest, MacroInLoopTest) {
- // Unlike the macros in histogram.h, SparseHistogram macros can have a
- // variable as histogram name.
- for (int i = 0; i < 2; i++) {
- UmaHistogramSparse(StringPrintf("Sparse%d", i), 100);
- }
-
- const StatisticsRecorder::Histograms histograms =
- StatisticsRecorder::Sort(StatisticsRecorder::GetHistograms());
- ASSERT_THAT(histograms, testing::SizeIs(2));
- EXPECT_STREQ(histograms[0]->histogram_name(), "Sparse0");
- EXPECT_STREQ(histograms[1]->histogram_name(), "Sparse1");
-}
-
-TEST_P(SparseHistogramTest, Serialize) {
- std::unique_ptr<SparseHistogram> histogram(NewSparseHistogram("Sparse"));
- histogram->SetFlags(HistogramBase::kIPCSerializationSourceFlag);
-
- Pickle pickle;
- histogram->SerializeInfo(&pickle);
-
- PickleIterator iter(pickle);
-
- int type;
- EXPECT_TRUE(iter.ReadInt(&type));
- EXPECT_EQ(SPARSE_HISTOGRAM, type);
-
- std::string name;
- EXPECT_TRUE(iter.ReadString(&name));
- EXPECT_EQ("Sparse", name);
-
- int flag;
- EXPECT_TRUE(iter.ReadInt(&flag));
- EXPECT_EQ(HistogramBase::kIPCSerializationSourceFlag, flag);
-
- // No more data in the pickle.
- EXPECT_FALSE(iter.SkipBytes(1));
-}
-
-// Ensure that race conditions that cause multiple, identical sparse histograms
-// to be created will safely resolve to a single one.
-TEST_P(SparseHistogramTest, DuplicationSafety) {
- const char histogram_name[] = "Duplicated";
- size_t histogram_count = StatisticsRecorder::GetHistogramCount();
-
- // Create a histogram that we will later duplicate.
- HistogramBase* original =
- SparseHistogram::FactoryGet(histogram_name, HistogramBase::kNoFlags);
- ++histogram_count;
- DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
- original->Add(1);
-
- // Create a duplicate. This has to happen differently depending on where the
- // memory is taken from.
- if (use_persistent_histogram_allocator_) {
- // To allocate from persistent memory, clear the last_created reference in
- // the GlobalHistogramAllocator. This will cause an Import to recreate
- // the just-created histogram which will then be released as a duplicate.
- GlobalHistogramAllocator::Get()->ClearLastCreatedReferenceForTesting();
- // Creating a different histogram will first do an Import to ensure it
- // hasn't been created elsewhere, triggering the duplication and release.
- SparseHistogram::FactoryGet("something.new", HistogramBase::kNoFlags);
- ++histogram_count;
- } else {
- // To allocate from the heap, just call the (private) constructor directly.
- // Delete it immediately like would have happened within FactoryGet();
- std::unique_ptr<SparseHistogram> something =
- NewSparseHistogram(histogram_name);
- DCHECK_NE(original, something.get());
- }
- DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
-
- // Re-creating the histogram via FactoryGet() will return the same one.
- HistogramBase* duplicate =
- SparseHistogram::FactoryGet(histogram_name, HistogramBase::kNoFlags);
- DCHECK_EQ(original, duplicate);
- DCHECK_EQ(histogram_count, StatisticsRecorder::GetHistogramCount());
- duplicate->Add(2);
-
- // Ensure that original histograms are still cross-functional.
- original->Add(2);
- duplicate->Add(1);
- std::unique_ptr<HistogramSamples> snapshot_orig = original->SnapshotSamples();
- std::unique_ptr<HistogramSamples> snapshot_dup = duplicate->SnapshotSamples();
- DCHECK_EQ(2, snapshot_orig->GetCount(2));
- DCHECK_EQ(2, snapshot_dup->GetCount(1));
-}
-
-TEST_P(SparseHistogramTest, FactoryTime) {
- const int kTestCreateCount = 1 << 10; // Must be power-of-2.
- const int kTestLookupCount = 100000;
- const int kTestAddCount = 100000;
-
- // Create all histogram names in advance for accurate timing below.
- std::vector<std::string> histogram_names;
- for (int i = 0; i < kTestCreateCount; ++i) {
- histogram_names.push_back(
- StringPrintf("TestHistogram.%d", i % kTestCreateCount));
- }
-
- // Calculate cost of creating histograms.
- TimeTicks create_start = TimeTicks::Now();
- for (int i = 0; i < kTestCreateCount; ++i)
- SparseHistogram::FactoryGet(histogram_names[i], HistogramBase::kNoFlags);
- TimeDelta create_ticks = TimeTicks::Now() - create_start;
- int64_t create_ms = create_ticks.InMilliseconds();
-
- VLOG(1) << kTestCreateCount << " histogram creations took " << create_ms
- << "ms or about "
- << (create_ms * 1000000) / kTestCreateCount
- << "ns each.";
-
- // Calculate cost of looking up existing histograms.
- TimeTicks lookup_start = TimeTicks::Now();
- for (int i = 0; i < kTestLookupCount; ++i) {
- // 6007 is co-prime with kTestCreateCount and so will do lookups in an
- // order less likely to be cacheable (but still hit them all) should the
- // underlying storage use the exact histogram name as the key.
- const int i_mult = 6007;
- static_assert(i_mult < INT_MAX / kTestCreateCount, "Multiplier too big");
- int index = (i * i_mult) & (kTestCreateCount - 1);
- SparseHistogram::FactoryGet(histogram_names[index],
- HistogramBase::kNoFlags);
- }
- TimeDelta lookup_ticks = TimeTicks::Now() - lookup_start;
- int64_t lookup_ms = lookup_ticks.InMilliseconds();
-
- VLOG(1) << kTestLookupCount << " histogram lookups took " << lookup_ms
- << "ms or about "
- << (lookup_ms * 1000000) / kTestLookupCount
- << "ns each.";
-
- // Calculate cost of accessing histograms.
- HistogramBase* histogram =
- SparseHistogram::FactoryGet(histogram_names[0], HistogramBase::kNoFlags);
- ASSERT_TRUE(histogram);
- TimeTicks add_start = TimeTicks::Now();
- for (int i = 0; i < kTestAddCount; ++i)
- histogram->Add(i & 127);
- TimeDelta add_ticks = TimeTicks::Now() - add_start;
- int64_t add_ms = add_ticks.InMilliseconds();
-
- VLOG(1) << kTestAddCount << " histogram adds took " << add_ms
- << "ms or about "
- << (add_ms * 1000000) / kTestAddCount
- << "ns each.";
-}
-
-TEST_P(SparseHistogramTest, ExtremeValues) {
- static const struct {
- Histogram::Sample sample;
- int64_t expected_max;
- } cases[] = {
- // Note: We use -2147483647 - 1 rather than -2147483648 because the later
- // is interpreted as - operator applied to 2147483648 and the latter can't
- // be represented as an int32 and causes a warning.
- {-2147483647 - 1, -2147483647LL},
- {0, 1},
- {2147483647, 2147483648LL},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- HistogramBase* histogram =
- SparseHistogram::FactoryGet(StringPrintf("ExtremeValues_%zu", i),
- HistogramBase::kUmaTargetedHistogramFlag);
- histogram->Add(cases[i].sample);
-
- std::unique_ptr<HistogramSamples> snapshot = histogram->SnapshotSamples();
- std::unique_ptr<SampleCountIterator> it = snapshot->Iterator();
- ASSERT_FALSE(it->Done());
-
- base::Histogram::Sample min;
- int64_t max;
- base::Histogram::Count count;
- it->Get(&min, &max, &count);
-
- EXPECT_EQ(1, count);
- EXPECT_EQ(cases[i].sample, min);
- EXPECT_EQ(cases[i].expected_max, max);
-
- it->Next();
- EXPECT_TRUE(it->Done());
- }
-}
-
-TEST_P(SparseHistogramTest, HistogramNameHash) {
- const char kName[] = "TestName";
- HistogramBase* histogram = SparseHistogram::FactoryGet(
- kName, HistogramBase::kUmaTargetedHistogramFlag);
- EXPECT_EQ(histogram->name_hash(), HashMetricName(kName));
-}
-
-} // namespace base
diff --git a/base/metrics/statistics_recorder_unittest.cc b/base/metrics/statistics_recorder_unittest.cc
deleted file mode 100644
index 63ba136..0000000
--- a/base/metrics/statistics_recorder_unittest.cc
+++ /dev/null
@@ -1,718 +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/metrics/statistics_recorder.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/json/json_reader.h"
-#include "base/logging.h"
-#include "base/memory/weak_ptr.h"
-#include "base/metrics/histogram_base.h"
-#include "base/metrics/histogram_macros.h"
-#include "base/metrics/persistent_histogram_allocator.h"
-#include "base/metrics/record_histogram_checker.h"
-#include "base/metrics/sparse_histogram.h"
-#include "base/values.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Class to make sure any manipulations we do to the min log level are
-// contained (i.e., do not affect other unit tests).
-class LogStateSaver {
- public:
- LogStateSaver() : old_min_log_level_(logging::GetMinLogLevel()) {}
-
- ~LogStateSaver() { logging::SetMinLogLevel(old_min_log_level_); }
-
- private:
- int old_min_log_level_;
-
- DISALLOW_COPY_AND_ASSIGN(LogStateSaver);
-};
-
-// Test implementation of RecordHistogramChecker interface.
-class OddRecordHistogramChecker : public base::RecordHistogramChecker {
- public:
- ~OddRecordHistogramChecker() override = default;
-
- // base::RecordHistogramChecker:
- bool ShouldRecord(uint64_t histogram_hash) const override {
- return histogram_hash % 2;
- }
-};
-
-} // namespace
-
-namespace base {
-
-using testing::IsEmpty;
-using testing::SizeIs;
-using testing::UnorderedElementsAre;
-
-class StatisticsRecorderTest : public testing::TestWithParam<bool> {
- protected:
- const int32_t kAllocatorMemorySize = 64 << 10; // 64 KiB
-
- StatisticsRecorderTest() : use_persistent_histogram_allocator_(GetParam()) {
- // Each test will have a clean state (no Histogram / BucketRanges
- // registered).
- InitializeStatisticsRecorder();
-
- // Use persistent memory for histograms if so indicated by test parameter.
- if (use_persistent_histogram_allocator_) {
- GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0,
- "StatisticsRecorderTest");
- }
- }
-
- ~StatisticsRecorderTest() override {
- GlobalHistogramAllocator::ReleaseForTesting();
- UninitializeStatisticsRecorder();
- }
-
- void InitializeStatisticsRecorder() {
- DCHECK(!statistics_recorder_);
- statistics_recorder_ = StatisticsRecorder::CreateTemporaryForTesting();
- }
-
- // Deletes the global recorder if there is any. This is used by test
- // NotInitialized to ensure a clean global state.
- void UninitializeStatisticsRecorder() {
- statistics_recorder_.reset();
- delete StatisticsRecorder::top_;
- DCHECK(!StatisticsRecorder::top_);
- }
-
- bool HasGlobalRecorder() { return StatisticsRecorder::top_ != nullptr; }
-
- Histogram* CreateHistogram(const char* name,
- HistogramBase::Sample min,
- HistogramBase::Sample max,
- size_t bucket_count) {
- BucketRanges* ranges = new BucketRanges(bucket_count + 1);
- Histogram::InitializeBucketRanges(min, max, ranges);
- const BucketRanges* registered_ranges =
- StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges);
- return new Histogram(name, min, max, registered_ranges);
- }
-
- void InitLogOnShutdown() { StatisticsRecorder::InitLogOnShutdown(); }
-
- bool IsVLogInitialized() { return StatisticsRecorder::is_vlog_initialized_; }
-
- void ResetVLogInitialized() {
- UninitializeStatisticsRecorder();
- StatisticsRecorder::is_vlog_initialized_ = false;
- }
-
- const bool use_persistent_histogram_allocator_;
-
- std::unique_ptr<StatisticsRecorder> statistics_recorder_;
- std::unique_ptr<GlobalHistogramAllocator> old_global_allocator_;
-
- private:
- LogStateSaver log_state_saver_;
-
- DISALLOW_COPY_AND_ASSIGN(StatisticsRecorderTest);
-};
-
-// Run all HistogramTest cases with both heap and persistent memory.
-INSTANTIATE_TEST_CASE_P(Allocator, StatisticsRecorderTest, testing::Bool());
-
-TEST_P(StatisticsRecorderTest, NotInitialized) {
- UninitializeStatisticsRecorder();
- EXPECT_FALSE(HasGlobalRecorder());
-
- HistogramBase* const histogram =
- CreateHistogram("TestHistogram", 1, 1000, 10);
- EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicate(histogram),
- histogram);
- EXPECT_TRUE(HasGlobalRecorder());
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram));
-
- UninitializeStatisticsRecorder();
- EXPECT_FALSE(HasGlobalRecorder());
-
- BucketRanges* const ranges = new BucketRanges(3);
- ranges->ResetChecksum();
- EXPECT_EQ(StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges),
- ranges);
- EXPECT_TRUE(HasGlobalRecorder());
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
- UnorderedElementsAre(ranges));
-}
-
-TEST_P(StatisticsRecorderTest, RegisterBucketRanges) {
- std::vector<const BucketRanges*> registered_ranges;
-
- BucketRanges* ranges1 = new BucketRanges(3);
- ranges1->ResetChecksum();
- BucketRanges* ranges2 = new BucketRanges(4);
- ranges2->ResetChecksum();
-
- // Register new ranges.
- EXPECT_EQ(ranges1,
- StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
- EXPECT_EQ(ranges2,
- StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges2));
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
- UnorderedElementsAre(ranges1, ranges2));
-
- // Register some ranges again.
- EXPECT_EQ(ranges1,
- StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges1));
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
- UnorderedElementsAre(ranges1, ranges2));
-
- // Make sure the ranges is still the one we know.
- ASSERT_EQ(3u, ranges1->size());
- EXPECT_EQ(0, ranges1->range(0));
- EXPECT_EQ(0, ranges1->range(1));
- EXPECT_EQ(0, ranges1->range(2));
-
- // Register ranges with same values.
- BucketRanges* ranges3 = new BucketRanges(3);
- ranges3->ResetChecksum();
- EXPECT_EQ(ranges1, // returning ranges1
- StatisticsRecorder::RegisterOrDeleteDuplicateRanges(ranges3));
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(),
- UnorderedElementsAre(ranges1, ranges2));
-}
-
-TEST_P(StatisticsRecorderTest, RegisterHistogram) {
- // Create a Histogram that was not registered.
- Histogram* const histogram1 = CreateHistogram("TestHistogram1", 1, 1000, 10);
-
- EXPECT_THAT(StatisticsRecorder::GetHistograms(), IsEmpty());
-
- // Register the Histogram.
- EXPECT_EQ(histogram1,
- StatisticsRecorder::RegisterOrDeleteDuplicate(histogram1));
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1));
-
- // Register the same Histogram again.
- EXPECT_EQ(histogram1,
- StatisticsRecorder::RegisterOrDeleteDuplicate(histogram1));
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1));
-
- // Register another Histogram with the same name.
- Histogram* const histogram2 = CreateHistogram("TestHistogram1", 1, 1000, 10);
- EXPECT_NE(histogram1, histogram2);
- EXPECT_EQ(histogram1,
- StatisticsRecorder::RegisterOrDeleteDuplicate(histogram2));
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1));
-
- // Register another Histogram with a different name.
- Histogram* const histogram3 = CreateHistogram("TestHistogram0", 1, 1000, 10);
- EXPECT_NE(histogram1, histogram3);
- EXPECT_EQ(histogram3,
- StatisticsRecorder::RegisterOrDeleteDuplicate(histogram3));
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1, histogram3));
-}
-
-TEST_P(StatisticsRecorderTest, FindHistogram) {
- HistogramBase* histogram1 = Histogram::FactoryGet(
- "TestHistogram1", 1, 1000, 10, HistogramBase::kNoFlags);
- HistogramBase* histogram2 = Histogram::FactoryGet(
- "TestHistogram2", 1, 1000, 10, HistogramBase::kNoFlags);
-
- EXPECT_EQ(histogram1, StatisticsRecorder::FindHistogram("TestHistogram1"));
- EXPECT_EQ(histogram2, StatisticsRecorder::FindHistogram("TestHistogram2"));
- EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram"));
-
- // Create a new global allocator using the same memory as the old one. Any
- // old one is kept around so the memory doesn't get released.
- old_global_allocator_ = GlobalHistogramAllocator::ReleaseForTesting();
- if (use_persistent_histogram_allocator_) {
- GlobalHistogramAllocator::CreateWithPersistentMemory(
- const_cast<void*>(old_global_allocator_->data()),
- old_global_allocator_->length(), 0, old_global_allocator_->Id(),
- old_global_allocator_->Name());
- }
-
- // Reset statistics-recorder to validate operation from a clean start.
- UninitializeStatisticsRecorder();
- InitializeStatisticsRecorder();
-
- if (use_persistent_histogram_allocator_) {
- EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram1"));
- EXPECT_TRUE(StatisticsRecorder::FindHistogram("TestHistogram2"));
- } else {
- EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram1"));
- EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram2"));
- }
- EXPECT_FALSE(StatisticsRecorder::FindHistogram("TestHistogram"));
-}
-
-TEST_P(StatisticsRecorderTest, WithName) {
- Histogram::FactoryGet("TestHistogram1", 1, 1000, 10, Histogram::kNoFlags);
- Histogram::FactoryGet("TestHistogram2", 1, 1000, 10, Histogram::kNoFlags);
- Histogram::FactoryGet("TestHistogram3", 1, 1000, 10, Histogram::kNoFlags);
-
- const auto histograms = StatisticsRecorder::GetHistograms();
- EXPECT_THAT(histograms, SizeIs(3));
- EXPECT_THAT(StatisticsRecorder::WithName(histograms, ""), SizeIs(3));
- EXPECT_THAT(StatisticsRecorder::WithName(histograms, "Test"), SizeIs(3));
- EXPECT_THAT(StatisticsRecorder::WithName(histograms, "1"), SizeIs(1));
- EXPECT_THAT(StatisticsRecorder::WithName(histograms, "hello"), IsEmpty());
-}
-
-TEST_P(StatisticsRecorderTest, RegisterHistogramWithFactoryGet) {
- EXPECT_THAT(StatisticsRecorder::GetHistograms(), IsEmpty());
-
- // Create a histogram.
- HistogramBase* const histogram1 = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1));
-
- // Get an existing histogram.
- HistogramBase* const histogram2 = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- EXPECT_EQ(histogram1, histogram2);
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1));
-
- // Create a LinearHistogram.
- HistogramBase* const histogram3 = LinearHistogram::FactoryGet(
- "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1, histogram3));
-
- // Create a BooleanHistogram.
- HistogramBase* const histogram4 = BooleanHistogram::FactoryGet(
- "TestBooleanHistogram", HistogramBase::kNoFlags);
- EXPECT_THAT(StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1, histogram3, histogram4));
-
- // Create a CustomHistogram.
- std::vector<int> custom_ranges;
- custom_ranges.push_back(1);
- custom_ranges.push_back(5);
- HistogramBase* const histogram5 = CustomHistogram::FactoryGet(
- "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
- EXPECT_THAT(
- StatisticsRecorder::GetHistograms(),
- UnorderedElementsAre(histogram1, histogram3, histogram4, histogram5));
-}
-
-TEST_P(StatisticsRecorderTest, RegisterHistogramWithMacros) {
- // Macros cache pointers and so tests that use them can only be run once.
- // Stop immediately if this test has run previously.
- static bool already_run = false;
- if (already_run)
- return;
- already_run = true;
-
- StatisticsRecorder::Histograms registered_histograms;
-
- HistogramBase* histogram = Histogram::FactoryGet(
- "TestHistogramCounts", 1, 1000000, 50, HistogramBase::kNoFlags);
-
- // The histogram we got from macro is the same as from FactoryGet.
- LOCAL_HISTOGRAM_COUNTS("TestHistogramCounts", 30);
- registered_histograms = StatisticsRecorder::GetHistograms();
- ASSERT_EQ(1u, registered_histograms.size());
- EXPECT_EQ(histogram, registered_histograms[0]);
-
- LOCAL_HISTOGRAM_TIMES("TestHistogramTimes", TimeDelta::FromDays(1));
- LOCAL_HISTOGRAM_ENUMERATION("TestHistogramEnumeration", 20, 200);
-
- EXPECT_THAT(StatisticsRecorder::GetHistograms(), SizeIs(3));
-}
-
-TEST_P(StatisticsRecorderTest, BucketRangesSharing) {
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), IsEmpty());
-
- Histogram::FactoryGet("Histogram", 1, 64, 8, HistogramBase::kNoFlags);
- Histogram::FactoryGet("Histogram2", 1, 64, 8, HistogramBase::kNoFlags);
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), SizeIs(1));
-
- Histogram::FactoryGet("Histogram3", 1, 64, 16, HistogramBase::kNoFlags);
- EXPECT_THAT(StatisticsRecorder::GetBucketRanges(), SizeIs(2));
-}
-
-TEST_P(StatisticsRecorderTest, ToJSON) {
- Histogram::FactoryGet("TestHistogram1", 1, 1000, 50, HistogramBase::kNoFlags)
- ->Add(30);
- Histogram::FactoryGet("TestHistogram1", 1, 1000, 50, HistogramBase::kNoFlags)
- ->Add(40);
- Histogram::FactoryGet("TestHistogram2", 1, 1000, 50, HistogramBase::kNoFlags)
- ->Add(30);
- Histogram::FactoryGet("TestHistogram2", 1, 1000, 50, HistogramBase::kNoFlags)
- ->Add(40);
-
- std::string json(StatisticsRecorder::ToJSON(JSON_VERBOSITY_LEVEL_FULL));
-
- // Check for valid JSON.
- std::unique_ptr<Value> root = JSONReader::Read(json);
- ASSERT_TRUE(root.get());
-
- DictionaryValue* root_dict = nullptr;
- ASSERT_TRUE(root->GetAsDictionary(&root_dict));
-
- // No query should be set.
- ASSERT_FALSE(root_dict->HasKey("query"));
-
- ListValue* histogram_list = nullptr;
- ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
- ASSERT_EQ(2u, histogram_list->GetSize());
-
- // Examine the first histogram.
- DictionaryValue* histogram_dict = nullptr;
- ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
-
- int sample_count;
- ASSERT_TRUE(histogram_dict->GetInteger("count", &sample_count));
- EXPECT_EQ(2, sample_count);
-
- ListValue* buckets_list = nullptr;
- ASSERT_TRUE(histogram_dict->GetList("buckets", &buckets_list));
- EXPECT_EQ(2u, buckets_list->GetList().size());
-
- // Check the serialized JSON with a different verbosity level.
- json = StatisticsRecorder::ToJSON(JSON_VERBOSITY_LEVEL_OMIT_BUCKETS);
- root = JSONReader::Read(json);
- ASSERT_TRUE(root.get());
- root_dict = nullptr;
- ASSERT_TRUE(root->GetAsDictionary(&root_dict));
- histogram_list = nullptr;
- ASSERT_TRUE(root_dict->GetList("histograms", &histogram_list));
- ASSERT_EQ(2u, histogram_list->GetSize());
- histogram_dict = nullptr;
- ASSERT_TRUE(histogram_list->GetDictionary(0, &histogram_dict));
- sample_count = 0;
- ASSERT_TRUE(histogram_dict->GetInteger("count", &sample_count));
- EXPECT_EQ(2, sample_count);
- buckets_list = nullptr;
- // Bucket information should be omitted.
- ASSERT_FALSE(histogram_dict->GetList("buckets", &buckets_list));
-}
-
-TEST_P(StatisticsRecorderTest, IterationTest) {
- Histogram::FactoryGet("IterationTest1", 1, 64, 16, HistogramBase::kNoFlags);
- Histogram::FactoryGet("IterationTest2", 1, 64, 16, HistogramBase::kNoFlags);
-
- auto histograms = StatisticsRecorder::GetHistograms();
- EXPECT_THAT(histograms, SizeIs(2));
- histograms = StatisticsRecorder::NonPersistent(std::move(histograms));
- EXPECT_THAT(histograms, SizeIs(use_persistent_histogram_allocator_ ? 0 : 2));
-
- // Create a new global allocator using the same memory as the old one. Any
- // old one is kept around so the memory doesn't get released.
- old_global_allocator_ = GlobalHistogramAllocator::ReleaseForTesting();
- if (use_persistent_histogram_allocator_) {
- GlobalHistogramAllocator::CreateWithPersistentMemory(
- const_cast<void*>(old_global_allocator_->data()),
- old_global_allocator_->length(), 0, old_global_allocator_->Id(),
- old_global_allocator_->Name());
- }
-
- // Reset statistics-recorder to validate operation from a clean start.
- UninitializeStatisticsRecorder();
- InitializeStatisticsRecorder();
-
- histograms = StatisticsRecorder::GetHistograms();
- EXPECT_THAT(histograms, SizeIs(use_persistent_histogram_allocator_ ? 2 : 0));
- histograms = StatisticsRecorder::NonPersistent(std::move(histograms));
- EXPECT_THAT(histograms, IsEmpty());
-}
-
-namespace {
-
-// CallbackCheckWrapper is simply a convenient way to check and store that
-// a callback was actually run.
-struct CallbackCheckWrapper {
- CallbackCheckWrapper() : called(false), last_histogram_value(0) {}
-
- void OnHistogramChanged(base::HistogramBase::Sample histogram_value) {
- called = true;
- last_histogram_value = histogram_value;
- }
-
- bool called;
- base::HistogramBase::Sample last_histogram_value;
-};
-
-} // namespace
-
-// Check that you can't overwrite the callback with another.
-TEST_P(StatisticsRecorderTest, SetCallbackFailsWithoutHistogramTest) {
- CallbackCheckWrapper callback_wrapper;
-
- bool result = base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
- EXPECT_TRUE(result);
-
- result = base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
- EXPECT_FALSE(result);
-}
-
-// Check that you can't overwrite the callback with another.
-TEST_P(StatisticsRecorderTest, SetCallbackFailsWithHistogramTest) {
- HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
- HistogramBase::kNoFlags);
- EXPECT_TRUE(histogram);
-
- CallbackCheckWrapper callback_wrapper;
-
- bool result = base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
- EXPECT_TRUE(result);
- EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
- base::HistogramBase::kCallbackExists);
-
- result = base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
- EXPECT_FALSE(result);
- EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
- base::HistogramBase::kCallbackExists);
-
- histogram->Add(1);
-
- EXPECT_TRUE(callback_wrapper.called);
-}
-
-// Check that you can't overwrite the callback with another.
-TEST_P(StatisticsRecorderTest, ClearCallbackSuceedsWithHistogramTest) {
- HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
- HistogramBase::kNoFlags);
- EXPECT_TRUE(histogram);
-
- CallbackCheckWrapper callback_wrapper;
-
- bool result = base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
- EXPECT_TRUE(result);
- EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists,
- base::HistogramBase::kCallbackExists);
-
- base::StatisticsRecorder::ClearCallback("TestHistogram");
- EXPECT_EQ(histogram->flags() & base::HistogramBase::kCallbackExists, 0);
-
- histogram->Add(1);
-
- EXPECT_FALSE(callback_wrapper.called);
-}
-
-// Check that callback is used.
-TEST_P(StatisticsRecorderTest, CallbackUsedTest) {
- {
- HistogramBase* histogram = Histogram::FactoryGet(
- "TestHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
- EXPECT_TRUE(histogram);
-
- CallbackCheckWrapper callback_wrapper;
-
- base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
-
- histogram->Add(1);
-
- EXPECT_TRUE(callback_wrapper.called);
- EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
- }
-
- {
- HistogramBase* linear_histogram = LinearHistogram::FactoryGet(
- "TestLinearHistogram", 1, 1000, 10, HistogramBase::kNoFlags);
-
- CallbackCheckWrapper callback_wrapper;
-
- base::StatisticsRecorder::SetCallback(
- "TestLinearHistogram",
- base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
-
- linear_histogram->Add(1);
-
- EXPECT_TRUE(callback_wrapper.called);
- EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
- }
-
- {
- std::vector<int> custom_ranges;
- custom_ranges.push_back(1);
- custom_ranges.push_back(5);
- HistogramBase* custom_histogram = CustomHistogram::FactoryGet(
- "TestCustomHistogram", custom_ranges, HistogramBase::kNoFlags);
-
- CallbackCheckWrapper callback_wrapper;
-
- base::StatisticsRecorder::SetCallback(
- "TestCustomHistogram",
- base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
-
- custom_histogram->Add(1);
-
- EXPECT_TRUE(callback_wrapper.called);
- EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
- }
-
- {
- HistogramBase* custom_histogram = SparseHistogram::FactoryGet(
- "TestSparseHistogram", HistogramBase::kNoFlags);
-
- CallbackCheckWrapper callback_wrapper;
-
- base::StatisticsRecorder::SetCallback(
- "TestSparseHistogram",
- base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
-
- custom_histogram->Add(1);
-
- EXPECT_TRUE(callback_wrapper.called);
- EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
- }
-}
-
-// Check that setting a callback before the histogram exists works.
-TEST_P(StatisticsRecorderTest, CallbackUsedBeforeHistogramCreatedTest) {
- CallbackCheckWrapper callback_wrapper;
-
- base::StatisticsRecorder::SetCallback(
- "TestHistogram", base::Bind(&CallbackCheckWrapper::OnHistogramChanged,
- base::Unretained(&callback_wrapper)));
-
- HistogramBase* histogram = Histogram::FactoryGet("TestHistogram", 1, 1000, 10,
- HistogramBase::kNoFlags);
- EXPECT_TRUE(histogram);
- histogram->Add(1);
-
- EXPECT_TRUE(callback_wrapper.called);
- EXPECT_EQ(callback_wrapper.last_histogram_value, 1);
-}
-
-TEST_P(StatisticsRecorderTest, LogOnShutdownNotInitialized) {
- ResetVLogInitialized();
- logging::SetMinLogLevel(logging::LOG_WARNING);
- InitializeStatisticsRecorder();
- EXPECT_FALSE(VLOG_IS_ON(1));
- EXPECT_FALSE(IsVLogInitialized());
- InitLogOnShutdown();
- EXPECT_FALSE(IsVLogInitialized());
-}
-
-TEST_P(StatisticsRecorderTest, LogOnShutdownInitializedExplicitly) {
- ResetVLogInitialized();
- logging::SetMinLogLevel(logging::LOG_WARNING);
- InitializeStatisticsRecorder();
- EXPECT_FALSE(VLOG_IS_ON(1));
- EXPECT_FALSE(IsVLogInitialized());
- logging::SetMinLogLevel(logging::LOG_VERBOSE);
- EXPECT_TRUE(VLOG_IS_ON(1));
- InitLogOnShutdown();
- EXPECT_TRUE(IsVLogInitialized());
-}
-
-TEST_P(StatisticsRecorderTest, LogOnShutdownInitialized) {
- ResetVLogInitialized();
- logging::SetMinLogLevel(logging::LOG_VERBOSE);
- InitializeStatisticsRecorder();
- EXPECT_TRUE(VLOG_IS_ON(1));
- EXPECT_TRUE(IsVLogInitialized());
-}
-
-class TestHistogramProvider : public StatisticsRecorder::HistogramProvider {
- public:
- TestHistogramProvider(std::unique_ptr<PersistentHistogramAllocator> allocator)
- : allocator_(std::move(allocator)), weak_factory_(this) {
- StatisticsRecorder::RegisterHistogramProvider(weak_factory_.GetWeakPtr());
- }
-
- void MergeHistogramDeltas() override {
- PersistentHistogramAllocator::Iterator hist_iter(allocator_.get());
- while (true) {
- std::unique_ptr<base::HistogramBase> histogram = hist_iter.GetNext();
- if (!histogram)
- break;
- allocator_->MergeHistogramDeltaToStatisticsRecorder(histogram.get());
- }
- }
-
- private:
- std::unique_ptr<PersistentHistogramAllocator> allocator_;
- WeakPtrFactory<TestHistogramProvider> weak_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(TestHistogramProvider);
-};
-
-TEST_P(StatisticsRecorderTest, ImportHistogramsTest) {
- // Create a second SR to create some histograms for later import.
- std::unique_ptr<StatisticsRecorder> temp_sr =
- StatisticsRecorder::CreateTemporaryForTesting();
-
- // Extract any existing global allocator so a new one can be created.
- std::unique_ptr<GlobalHistogramAllocator> old_allocator =
- GlobalHistogramAllocator::ReleaseForTesting();
-
- // Create a histogram inside a new allocator for testing.
- GlobalHistogramAllocator::CreateWithLocalMemory(kAllocatorMemorySize, 0, "");
- HistogramBase* histogram = LinearHistogram::FactoryGet("Foo", 1, 10, 11, 0);
- histogram->Add(3);
-
- // Undo back to the starting point.
- std::unique_ptr<GlobalHistogramAllocator> new_allocator =
- GlobalHistogramAllocator::ReleaseForTesting();
- GlobalHistogramAllocator::Set(std::move(old_allocator));
- temp_sr.reset();
-
- // Create a provider that can supply histograms to the current SR.
- TestHistogramProvider provider(std::move(new_allocator));
-
- // Verify that the created histogram is no longer known.
- ASSERT_FALSE(StatisticsRecorder::FindHistogram(histogram->histogram_name()));
-
- // Now test that it merges.
- StatisticsRecorder::ImportProvidedHistograms();
- HistogramBase* found =
- StatisticsRecorder::FindHistogram(histogram->histogram_name());
- ASSERT_TRUE(found);
- EXPECT_NE(histogram, found);
- std::unique_ptr<HistogramSamples> snapshot = found->SnapshotSamples();
- EXPECT_EQ(1, snapshot->TotalCount());
- EXPECT_EQ(1, snapshot->GetCount(3));
-
- // Finally, verify that updates can also be merged.
- histogram->Add(3);
- histogram->Add(5);
- StatisticsRecorder::ImportProvidedHistograms();
- snapshot = found->SnapshotSamples();
- EXPECT_EQ(3, snapshot->TotalCount());
- EXPECT_EQ(2, snapshot->GetCount(3));
- EXPECT_EQ(1, snapshot->GetCount(5));
-}
-
-TEST_P(StatisticsRecorderTest, RecordHistogramChecker) {
- // Record checker isn't set
- EXPECT_TRUE(base::StatisticsRecorder::ShouldRecordHistogram(0));
- auto record_checker = std::make_unique<OddRecordHistogramChecker>();
- base::StatisticsRecorder::SetRecordChecker(std::move(record_checker));
- EXPECT_TRUE(base::StatisticsRecorder::ShouldRecordHistogram(1));
- EXPECT_FALSE(base::StatisticsRecorder::ShouldRecordHistogram(2));
-}
-
-} // namespace base
diff --git a/base/native_library_unittest.cc b/base/native_library_unittest.cc
deleted file mode 100644
index ac8ec5c..0000000
--- 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_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/xdg_util_unittest.cc b/base/nix/xdg_util_unittest.cc
deleted file mode 100644
index e195303..0000000
--- 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/no_destructor_unittest.cc b/base/no_destructor_unittest.cc
deleted file mode 100644
index c552a92..0000000
--- a/base/no_destructor_unittest.cc
+++ /dev/null
@@ -1,76 +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/no_destructor.h"
-
-#include <string>
-#include <utility>
-
-#include "base/logging.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-struct CheckOnDestroy {
- ~CheckOnDestroy() { CHECK(false); }
-};
-
-TEST(NoDestructorTest, SkipsDestructors) {
- NoDestructor<CheckOnDestroy> destructor_should_not_run;
-}
-
-struct CopyOnly {
- CopyOnly() = default;
-
- CopyOnly(const CopyOnly&) = default;
- CopyOnly& operator=(const CopyOnly&) = default;
-
- CopyOnly(CopyOnly&&) = delete;
- CopyOnly& operator=(CopyOnly&&) = delete;
-};
-
-struct MoveOnly {
- MoveOnly() = default;
-
- MoveOnly(const MoveOnly&) = delete;
- MoveOnly& operator=(const MoveOnly&) = delete;
-
- MoveOnly(MoveOnly&&) = default;
- MoveOnly& operator=(MoveOnly&&) = default;
-};
-
-struct ForwardingTestStruct {
- ForwardingTestStruct(const CopyOnly&, MoveOnly&&) {}
-};
-
-TEST(NoDestructorTest, ForwardsArguments) {
- CopyOnly copy_only;
- MoveOnly move_only;
-
- static NoDestructor<ForwardingTestStruct> test_forwarding(
- copy_only, std::move(move_only));
-}
-
-TEST(NoDestructorTest, Accessors) {
- static NoDestructor<std::string> awesome("awesome");
-
- EXPECT_EQ("awesome", *awesome);
- EXPECT_EQ(0, awesome->compare("awesome"));
- EXPECT_EQ(0, awesome.get()->compare("awesome"));
-}
-
-// Passing initializer list to a NoDestructor like in this test
-// is ambiguous in GCC.
-// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=84849
-#if !defined(COMPILER_GCC) && !defined(__clang__)
-TEST(NoDestructorTest, InitializerList) {
- static NoDestructor<std::vector<std::string>> vector({"a", "b", "c"});
-}
-#endif
-} // namespace
-
-} // namespace base
diff --git a/base/numerics/BUILD.gn b/base/numerics/BUILD.gn
deleted file mode 100644
index 0bb8dd1..0000000
--- a/base/numerics/BUILD.gn
+++ /dev/null
@@ -1,28 +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.
-
-# 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/observer_list_unittest.cc b/base/observer_list_unittest.cc
deleted file mode 100644
index 37629ef..0000000
--- a/base/observer_list_unittest.cc
+++ /dev/null
@@ -1,1276 +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/observer_list.h"
-#include "base/observer_list_threadsafe.h"
-
-#include <memory>
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/location.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/sequenced_task_runner.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "base/test/gtest_util.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class Foo {
- public:
- virtual void Observe(int x) = 0;
- virtual ~Foo() = default;
- virtual int GetValue() const { return 0; }
-};
-
-class Adder : public Foo {
- public:
- explicit Adder(int scaler) : total(0), scaler_(scaler) {}
- ~Adder() override = default;
-
- void Observe(int x) override { total += x * scaler_; }
- int GetValue() const override { return total; }
-
- int total;
-
- private:
- int scaler_;
-};
-
-class Disrupter : public Foo {
- public:
- Disrupter(ObserverList<Foo>* list, Foo* doomed, bool remove_self)
- : list_(list), doomed_(doomed), remove_self_(remove_self) {}
- Disrupter(ObserverList<Foo>* list, Foo* doomed)
- : Disrupter(list, doomed, false) {}
- Disrupter(ObserverList<Foo>* list, bool remove_self)
- : Disrupter(list, nullptr, remove_self) {}
-
- ~Disrupter() override = default;
-
- void Observe(int x) override {
- if (remove_self_)
- list_->RemoveObserver(this);
- if (doomed_)
- list_->RemoveObserver(doomed_);
- }
-
- void SetDoomed(Foo* doomed) { doomed_ = doomed; }
-
- private:
- ObserverList<Foo>* list_;
- Foo* doomed_;
- bool remove_self_;
-};
-
-template <typename ObserverListType>
-class AddInObserve : public Foo {
- public:
- explicit AddInObserve(ObserverListType* observer_list)
- : observer_list(observer_list), to_add_() {}
-
- void SetToAdd(Foo* to_add) { to_add_ = to_add; }
-
- void Observe(int x) override {
- if (to_add_) {
- observer_list->AddObserver(to_add_);
- to_add_ = nullptr;
- }
- }
-
- ObserverListType* observer_list;
- Foo* to_add_;
-};
-
-
-static const int kThreadRunTime = 2000; // ms to run the multi-threaded test.
-
-// A thread for use in the ThreadSafeObserver test
-// which will add and remove itself from the notification
-// list repeatedly.
-class AddRemoveThread : public PlatformThread::Delegate,
- public Foo {
- public:
- AddRemoveThread(ObserverListThreadSafe<Foo>* list,
- bool notify,
- WaitableEvent* ready)
- : list_(list),
- loop_(nullptr),
- in_list_(false),
- start_(Time::Now()),
- count_observes_(0),
- count_addtask_(0),
- do_notifies_(notify),
- ready_(ready),
- weak_factory_(this) {}
-
- ~AddRemoveThread() override = default;
-
- void ThreadMain() override {
- loop_ = new MessageLoop(); // Fire up a message loop.
- loop_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
- ready_->Signal();
- // After ready_ is signaled, loop_ is only accessed by the main test thread
- // (i.e. not this thread) in particular by Quit() which causes Run() to
- // return, and we "control" loop_ again.
- RunLoop().Run();
- delete loop_;
- loop_ = reinterpret_cast<MessageLoop*>(0xdeadbeef);
- delete this;
- }
-
- // This task just keeps posting to itself in an attempt
- // to race with the notifier.
- void AddTask() {
- count_addtask_++;
-
- if ((Time::Now() - start_).InMilliseconds() > kThreadRunTime) {
- VLOG(1) << "DONE!";
- return;
- }
-
- if (!in_list_) {
- list_->AddObserver(this);
- in_list_ = true;
- }
-
- if (do_notifies_) {
- list_->Notify(FROM_HERE, &Foo::Observe, 10);
- }
-
- loop_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&AddRemoveThread::AddTask, weak_factory_.GetWeakPtr()));
- }
-
- // This function is only callable from the main thread.
- void Quit() {
- loop_->task_runner()->PostTask(
- FROM_HERE, RunLoop::QuitCurrentWhenIdleClosureDeprecated());
- }
-
- void Observe(int x) override {
- count_observes_++;
-
- // If we're getting called after we removed ourselves from
- // the list, that is very bad!
- DCHECK(in_list_);
-
- // This callback should fire on the appropriate thread
- EXPECT_EQ(loop_, MessageLoop::current());
-
- list_->RemoveObserver(this);
- in_list_ = false;
- }
-
- private:
- ObserverListThreadSafe<Foo>* list_;
- MessageLoop* loop_;
- bool in_list_; // Are we currently registered for notifications.
- // in_list_ is only used on |this| thread.
- Time start_; // The time we started the test.
-
- int count_observes_; // Number of times we observed.
- int count_addtask_; // Number of times thread AddTask was called
- bool do_notifies_; // Whether these threads should do notifications.
- WaitableEvent* ready_;
-
- base::WeakPtrFactory<AddRemoveThread> weak_factory_;
-};
-
-} // namespace
-
-TEST(ObserverListTest, BasicTest) {
- ObserverList<Foo> observer_list;
- const ObserverList<Foo>& const_observer_list = observer_list;
-
- {
- const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
- EXPECT_EQ(it1, const_observer_list.end());
- // Iterator copy.
- const ObserverList<Foo>::const_iterator it2 = it1;
- EXPECT_EQ(it2, it1);
- // Iterator assignment.
- ObserverList<Foo>::const_iterator it3;
- it3 = it2;
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- // Self assignment.
- it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- }
-
- {
- const ObserverList<Foo>::iterator it1 = observer_list.begin();
- EXPECT_EQ(it1, observer_list.end());
- // Iterator copy.
- const ObserverList<Foo>::iterator it2 = it1;
- EXPECT_EQ(it2, it1);
- // Iterator assignment.
- ObserverList<Foo>::iterator it3;
- it3 = it2;
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- // Self assignment.
- it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- }
-
- Adder a(1), b(-1), c(1), d(-1), e(-1);
- Disrupter evil(&observer_list, &c);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
-
- EXPECT_TRUE(const_observer_list.HasObserver(&a));
- EXPECT_FALSE(const_observer_list.HasObserver(&c));
-
- {
- const ObserverList<Foo>::const_iterator it1 = const_observer_list.begin();
- EXPECT_NE(it1, const_observer_list.end());
- // Iterator copy.
- const ObserverList<Foo>::const_iterator it2 = it1;
- EXPECT_EQ(it2, it1);
- EXPECT_NE(it2, const_observer_list.end());
- // Iterator assignment.
- ObserverList<Foo>::const_iterator it3;
- it3 = it2;
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- // Self assignment.
- it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- // Iterator post increment.
- ObserverList<Foo>::const_iterator it4 = it3++;
- EXPECT_EQ(it4, it1);
- EXPECT_EQ(it4, it2);
- EXPECT_NE(it4, it3);
- }
-
- {
- const ObserverList<Foo>::iterator it1 = observer_list.begin();
- EXPECT_NE(it1, observer_list.end());
- // Iterator copy.
- const ObserverList<Foo>::iterator it2 = it1;
- EXPECT_EQ(it2, it1);
- EXPECT_NE(it2, observer_list.end());
- // Iterator assignment.
- ObserverList<Foo>::iterator it3;
- it3 = it2;
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- // Self assignment.
- it3 = *&it3; // The *& defeats Clang's -Wself-assign warning.
- EXPECT_EQ(it3, it1);
- EXPECT_EQ(it3, it2);
- // Iterator post increment.
- ObserverList<Foo>::iterator it4 = it3++;
- EXPECT_EQ(it4, it1);
- EXPECT_EQ(it4, it2);
- EXPECT_NE(it4, it3);
- }
-
- for (auto& observer : observer_list)
- observer.Observe(10);
-
- observer_list.AddObserver(&evil);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- // Removing an observer not in the list should do nothing.
- observer_list.RemoveObserver(&e);
-
- for (auto& observer : observer_list)
- observer.Observe(10);
-
- EXPECT_EQ(20, a.total);
- EXPECT_EQ(-20, b.total);
- EXPECT_EQ(0, c.total);
- EXPECT_EQ(-10, d.total);
- EXPECT_EQ(0, e.total);
-}
-
-TEST(ObserverListTest, CompactsWhenNoActiveIterator) {
- ObserverList<const Foo> ol;
- const ObserverList<const Foo>& col = ol;
-
- const Adder a(1);
- const Adder b(2);
- const Adder c(3);
-
- ol.AddObserver(&a);
- ol.AddObserver(&b);
-
- EXPECT_TRUE(col.HasObserver(&a));
- EXPECT_FALSE(col.HasObserver(&c));
-
- EXPECT_TRUE(col.might_have_observers());
-
- using It = ObserverList<const Foo>::const_iterator;
-
- {
- It it = col.begin();
- EXPECT_NE(it, col.end());
- It ita = it;
- EXPECT_EQ(ita, it);
- EXPECT_NE(++it, col.end());
- EXPECT_NE(ita, it);
- It itb = it;
- EXPECT_EQ(itb, it);
- EXPECT_EQ(++it, col.end());
-
- EXPECT_TRUE(col.might_have_observers());
- EXPECT_EQ(&*ita, &a);
- EXPECT_EQ(&*itb, &b);
-
- ol.RemoveObserver(&a);
- EXPECT_TRUE(col.might_have_observers());
- EXPECT_FALSE(col.HasObserver(&a));
- EXPECT_EQ(&*itb, &b);
-
- ol.RemoveObserver(&b);
- EXPECT_TRUE(col.might_have_observers());
- EXPECT_FALSE(col.HasObserver(&a));
- EXPECT_FALSE(col.HasObserver(&b));
-
- it = It();
- ita = It();
- EXPECT_TRUE(col.might_have_observers());
- ita = itb;
- itb = It();
- EXPECT_TRUE(col.might_have_observers());
- ita = It();
- EXPECT_FALSE(col.might_have_observers());
- }
-
- ol.AddObserver(&a);
- ol.AddObserver(&b);
- EXPECT_TRUE(col.might_have_observers());
- ol.Clear();
- EXPECT_FALSE(col.might_have_observers());
-
- ol.AddObserver(&a);
- ol.AddObserver(&b);
- EXPECT_TRUE(col.might_have_observers());
- {
- const It it = col.begin();
- ol.Clear();
- EXPECT_TRUE(col.might_have_observers());
- }
- EXPECT_FALSE(col.might_have_observers());
-}
-
-TEST(ObserverListTest, DisruptSelf) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter evil(&observer_list, true);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
-
- for (auto& observer : observer_list)
- observer.Observe(10);
-
- observer_list.AddObserver(&evil);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& observer : observer_list)
- observer.Observe(10);
-
- EXPECT_EQ(20, a.total);
- EXPECT_EQ(-20, b.total);
- EXPECT_EQ(10, c.total);
- EXPECT_EQ(-10, d.total);
-}
-
-TEST(ObserverListTest, DisruptBefore) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter evil(&observer_list, &b);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&evil);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& observer : observer_list)
- observer.Observe(10);
- for (auto& observer : observer_list)
- observer.Observe(10);
-
- EXPECT_EQ(20, a.total);
- EXPECT_EQ(-10, b.total);
- EXPECT_EQ(20, c.total);
- EXPECT_EQ(-20, d.total);
-}
-
-TEST(ObserverListThreadSafeTest, BasicTest) {
- MessageLoop loop;
-
- scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
- new ObserverListThreadSafe<Foo>);
- Adder a(1);
- Adder b(-1);
- Adder c(1);
- Adder d(-1);
-
- observer_list->AddObserver(&a);
- observer_list->AddObserver(&b);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
- RunLoop().RunUntilIdle();
-
- observer_list->AddObserver(&c);
- observer_list->AddObserver(&d);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
- observer_list->RemoveObserver(&c);
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(20, a.total);
- EXPECT_EQ(-20, b.total);
- EXPECT_EQ(0, c.total);
- EXPECT_EQ(-10, d.total);
-}
-
-TEST(ObserverListThreadSafeTest, RemoveObserver) {
- MessageLoop loop;
-
- scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
- new ObserverListThreadSafe<Foo>);
- Adder a(1), b(1);
-
- // A workaround for the compiler bug. See http://crbug.com/121960.
- EXPECT_NE(&a, &b);
-
- // Should do nothing.
- observer_list->RemoveObserver(&a);
- observer_list->RemoveObserver(&b);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(0, a.total);
- EXPECT_EQ(0, b.total);
-
- observer_list->AddObserver(&a);
-
- // Should also do nothing.
- observer_list->RemoveObserver(&b);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(10, a.total);
- EXPECT_EQ(0, b.total);
-}
-
-TEST(ObserverListThreadSafeTest, WithoutSequence) {
- scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
- new ObserverListThreadSafe<Foo>);
-
- Adder a(1), b(1), c(1);
-
- // No sequence, so these should not be added.
- observer_list->AddObserver(&a);
- observer_list->AddObserver(&b);
-
- {
- // Add c when there's a sequence.
- MessageLoop loop;
- observer_list->AddObserver(&c);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(0, a.total);
- EXPECT_EQ(0, b.total);
- EXPECT_EQ(10, c.total);
-
- // Now add a when there's a sequence.
- observer_list->AddObserver(&a);
-
- // Remove c when there's a sequence.
- observer_list->RemoveObserver(&c);
-
- // Notify again.
- observer_list->Notify(FROM_HERE, &Foo::Observe, 20);
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(20, a.total);
- EXPECT_EQ(0, b.total);
- EXPECT_EQ(10, c.total);
- }
-
- // Removing should always succeed with or without a sequence.
- observer_list->RemoveObserver(&a);
-
- // Notifying should not fail but should also be a no-op.
- MessageLoop loop;
- observer_list->AddObserver(&b);
- observer_list->Notify(FROM_HERE, &Foo::Observe, 30);
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(20, a.total);
- EXPECT_EQ(30, b.total);
- EXPECT_EQ(10, c.total);
-}
-
-class FooRemover : public Foo {
- public:
- explicit FooRemover(ObserverListThreadSafe<Foo>* list) : list_(list) {}
- ~FooRemover() override = default;
-
- void AddFooToRemove(Foo* foo) {
- foos_.push_back(foo);
- }
-
- void Observe(int x) override {
- std::vector<Foo*> tmp;
- tmp.swap(foos_);
- for (std::vector<Foo*>::iterator it = tmp.begin();
- it != tmp.end(); ++it) {
- list_->RemoveObserver(*it);
- }
- }
-
- private:
- const scoped_refptr<ObserverListThreadSafe<Foo> > list_;
- std::vector<Foo*> foos_;
-};
-
-TEST(ObserverListThreadSafeTest, RemoveMultipleObservers) {
- MessageLoop loop;
- scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
- new ObserverListThreadSafe<Foo>);
-
- FooRemover a(observer_list.get());
- Adder b(1);
-
- observer_list->AddObserver(&a);
- observer_list->AddObserver(&b);
-
- a.AddFooToRemove(&a);
- a.AddFooToRemove(&b);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
- RunLoop().RunUntilIdle();
-}
-
-// A test driver for a multi-threaded notification loop. Runs a number
-// of observer threads, each of which constantly adds/removes itself
-// from the observer list. Optionally, if cross_thread_notifies is set
-// to true, the observer threads will also trigger notifications to
-// all observers.
-static void ThreadSafeObserverHarness(int num_threads,
- bool cross_thread_notifies) {
- MessageLoop loop;
-
- scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
- new ObserverListThreadSafe<Foo>);
- Adder a(1);
- Adder b(-1);
-
- observer_list->AddObserver(&a);
- observer_list->AddObserver(&b);
-
- std::vector<AddRemoveThread*> threaded_observer;
- std::vector<base::PlatformThreadHandle> threads(num_threads);
- std::vector<std::unique_ptr<base::WaitableEvent>> ready;
- threaded_observer.reserve(num_threads);
- ready.reserve(num_threads);
- for (int index = 0; index < num_threads; index++) {
- ready.push_back(std::make_unique<WaitableEvent>(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED));
- threaded_observer.push_back(new AddRemoveThread(
- observer_list.get(), cross_thread_notifies, ready.back().get()));
- EXPECT_TRUE(
- PlatformThread::Create(0, threaded_observer.back(), &threads[index]));
- }
- ASSERT_EQ(static_cast<size_t>(num_threads), threaded_observer.size());
- ASSERT_EQ(static_cast<size_t>(num_threads), ready.size());
-
- // This makes sure that threaded_observer has gotten to set loop_, so that we
- // can call Quit() below safe-ish-ly.
- for (int i = 0; i < num_threads; ++i)
- ready[i]->Wait();
-
- Time start = Time::Now();
- while (true) {
- if ((Time::Now() - start).InMilliseconds() > kThreadRunTime)
- break;
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 10);
-
- RunLoop().RunUntilIdle();
- }
-
- for (int index = 0; index < num_threads; index++) {
- threaded_observer[index]->Quit();
- PlatformThread::Join(threads[index]);
- }
-}
-
-TEST(ObserverListThreadSafeTest, CrossThreadObserver) {
- // Use 7 observer threads. Notifications only come from
- // the main thread.
- ThreadSafeObserverHarness(7, false);
-}
-
-TEST(ObserverListThreadSafeTest, CrossThreadNotifications) {
- // Use 3 observer threads. Notifications will fire from
- // the main thread and all 3 observer threads.
- ThreadSafeObserverHarness(3, true);
-}
-
-TEST(ObserverListThreadSafeTest, OutlivesMessageLoop) {
- MessageLoop* loop = new MessageLoop;
- scoped_refptr<ObserverListThreadSafe<Foo> > observer_list(
- new ObserverListThreadSafe<Foo>);
-
- Adder a(1);
- observer_list->AddObserver(&a);
- delete loop;
- // Test passes if we don't crash here.
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
-}
-
-namespace {
-
-class SequenceVerificationObserver : public Foo {
- public:
- explicit SequenceVerificationObserver(
- scoped_refptr<SequencedTaskRunner> task_runner)
- : task_runner_(std::move(task_runner)) {}
- ~SequenceVerificationObserver() override = default;
-
- void Observe(int x) override {
- called_on_valid_sequence_ = task_runner_->RunsTasksInCurrentSequence();
- }
-
- bool called_on_valid_sequence() const { return called_on_valid_sequence_; }
-
- private:
- const scoped_refptr<SequencedTaskRunner> task_runner_;
- bool called_on_valid_sequence_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(SequenceVerificationObserver);
-};
-
-} // namespace
-
-// Verify that observers are notified on the correct sequence.
-TEST(ObserverListThreadSafeTest, NotificationOnValidSequence) {
- test::ScopedTaskEnvironment scoped_task_environment;
-
- auto task_runner_1 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
- auto task_runner_2 = CreateSequencedTaskRunnerWithTraits(TaskTraits());
-
- auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
-
- SequenceVerificationObserver observer_1(task_runner_1);
- SequenceVerificationObserver observer_2(task_runner_2);
-
- task_runner_1->PostTask(FROM_HERE,
- BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
- observer_list, Unretained(&observer_1)));
- task_runner_2->PostTask(FROM_HERE,
- BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
- observer_list, Unretained(&observer_2)));
-
- TaskScheduler::GetInstance()->FlushForTesting();
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
-
- TaskScheduler::GetInstance()->FlushForTesting();
-
- EXPECT_TRUE(observer_1.called_on_valid_sequence());
- EXPECT_TRUE(observer_2.called_on_valid_sequence());
-}
-
-// Verify that when an observer is added to a NOTIFY_ALL ObserverListThreadSafe
-// from a notification, it is itself notified.
-TEST(ObserverListThreadSafeTest, AddObserverFromNotificationNotifyAll) {
- test::ScopedTaskEnvironment scoped_task_environment;
- auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
-
- Adder observer_added_from_notification(1);
-
- AddInObserve<ObserverListThreadSafe<Foo>> initial_observer(
- observer_list.get());
- initial_observer.SetToAdd(&observer_added_from_notification);
- observer_list->AddObserver(&initial_observer);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
-
- base::RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, observer_added_from_notification.GetValue());
-}
-
-namespace {
-
-class RemoveWhileNotificationIsRunningObserver : public Foo {
- public:
- RemoveWhileNotificationIsRunningObserver()
- : notification_running_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- barrier_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
- ~RemoveWhileNotificationIsRunningObserver() override = default;
-
- void Observe(int x) override {
- notification_running_.Signal();
- ScopedAllowBaseSyncPrimitivesForTesting allow_base_sync_primitives;
- barrier_.Wait();
- }
-
- void WaitForNotificationRunning() { notification_running_.Wait(); }
- void Unblock() { barrier_.Signal(); }
-
- private:
- WaitableEvent notification_running_;
- WaitableEvent barrier_;
-
- DISALLOW_COPY_AND_ASSIGN(RemoveWhileNotificationIsRunningObserver);
-};
-
-} // namespace
-
-// Verify that there is no crash when an observer is removed while it is being
-// notified.
-TEST(ObserverListThreadSafeTest, RemoveWhileNotificationIsRunning) {
- auto observer_list = MakeRefCounted<ObserverListThreadSafe<Foo>>();
- RemoveWhileNotificationIsRunningObserver observer;
-
- WaitableEvent task_running(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent barrier(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // This must be after the declaration of |barrier| so that tasks posted to
- // TaskScheduler can safely use |barrier|.
- test::ScopedTaskEnvironment scoped_task_environment;
-
- CreateSequencedTaskRunnerWithTraits({})->PostTask(
- FROM_HERE, base::BindOnce(&ObserverListThreadSafe<Foo>::AddObserver,
- observer_list, Unretained(&observer)));
- TaskScheduler::GetInstance()->FlushForTesting();
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
- observer.WaitForNotificationRunning();
- observer_list->RemoveObserver(&observer);
-
- observer.Unblock();
-}
-
-TEST(ObserverListTest, Existing) {
- ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
- Adder a(1);
- AddInObserve<ObserverList<Foo> > b(&observer_list);
- Adder c(1);
- b.SetToAdd(&c);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
-
- for (auto& observer : observer_list)
- observer.Observe(1);
-
- EXPECT_FALSE(b.to_add_);
- // B's adder should not have been notified because it was added during
- // notification.
- EXPECT_EQ(0, c.total);
-
- // Notify again to make sure b's adder is notified.
- for (auto& observer : observer_list)
- observer.Observe(1);
- EXPECT_EQ(1, c.total);
-}
-
-// Same as above, but for ObserverListThreadSafe
-TEST(ObserverListThreadSafeTest, Existing) {
- MessageLoop loop;
- scoped_refptr<ObserverListThreadSafe<Foo>> observer_list(
- new ObserverListThreadSafe<Foo>(ObserverListPolicy::EXISTING_ONLY));
- Adder a(1);
- AddInObserve<ObserverListThreadSafe<Foo> > b(observer_list.get());
- Adder c(1);
- b.SetToAdd(&c);
-
- observer_list->AddObserver(&a);
- observer_list->AddObserver(&b);
-
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
- RunLoop().RunUntilIdle();
-
- EXPECT_FALSE(b.to_add_);
- // B's adder should not have been notified because it was added during
- // notification.
- EXPECT_EQ(0, c.total);
-
- // Notify again to make sure b's adder is notified.
- observer_list->Notify(FROM_HERE, &Foo::Observe, 1);
- RunLoop().RunUntilIdle();
- EXPECT_EQ(1, c.total);
-}
-
-class AddInClearObserve : public Foo {
- public:
- explicit AddInClearObserve(ObserverList<Foo>* list)
- : list_(list), added_(false), adder_(1) {}
-
- void Observe(int /* x */) override {
- list_->Clear();
- list_->AddObserver(&adder_);
- added_ = true;
- }
-
- bool added() const { return added_; }
- const Adder& adder() const { return adder_; }
-
- private:
- ObserverList<Foo>* const list_;
-
- bool added_;
- Adder adder_;
-};
-
-TEST(ObserverListTest, ClearNotifyAll) {
- ObserverList<Foo> observer_list;
- AddInClearObserve a(&observer_list);
-
- observer_list.AddObserver(&a);
-
- for (auto& observer : observer_list)
- observer.Observe(1);
- EXPECT_TRUE(a.added());
- EXPECT_EQ(1, a.adder().total)
- << "Adder should observe once and have sum of 1.";
-}
-
-TEST(ObserverListTest, ClearNotifyExistingOnly) {
- ObserverList<Foo> observer_list(ObserverListPolicy::EXISTING_ONLY);
- AddInClearObserve a(&observer_list);
-
- observer_list.AddObserver(&a);
-
- for (auto& observer : observer_list)
- observer.Observe(1);
- EXPECT_TRUE(a.added());
- EXPECT_EQ(0, a.adder().total)
- << "Adder should not observe, so sum should still be 0.";
-}
-
-class ListDestructor : public Foo {
- public:
- explicit ListDestructor(ObserverList<Foo>* list) : list_(list) {}
- ~ListDestructor() override = default;
-
- void Observe(int x) override { delete list_; }
-
- private:
- ObserverList<Foo>* list_;
-};
-
-
-TEST(ObserverListTest, IteratorOutlivesList) {
- ObserverList<Foo>* observer_list = new ObserverList<Foo>;
- ListDestructor a(observer_list);
- observer_list->AddObserver(&a);
-
- for (auto& observer : *observer_list)
- observer.Observe(0);
-
- // There are no EXPECT* statements for this test, if we catch
- // use-after-free errors for observer_list (eg with ASan) then
- // this test has failed. See http://crbug.com/85296.
-}
-
-TEST(ObserverListTest, BasicStdIterator) {
- using FooList = ObserverList<Foo>;
- FooList observer_list;
-
- // An optimization: begin() and end() do not involve weak pointers on
- // empty list.
- EXPECT_FALSE(observer_list.begin().list_);
- EXPECT_FALSE(observer_list.end().list_);
-
- // Iterate over empty list: no effect, no crash.
- for (auto& i : observer_list)
- i.Observe(10);
-
- Adder a(1), b(-1), c(1), d(-1);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
- i != e; ++i)
- i->Observe(1);
-
- EXPECT_EQ(1, a.total);
- EXPECT_EQ(-1, b.total);
- EXPECT_EQ(1, c.total);
- EXPECT_EQ(-1, d.total);
-
- // Check an iteration over a 'const view' for a given container.
- const FooList& const_list = observer_list;
- for (FooList::const_iterator i = const_list.begin(), e = const_list.end();
- i != e; ++i) {
- EXPECT_EQ(1, std::abs(i->GetValue()));
- }
-
- for (const auto& o : const_list)
- EXPECT_EQ(1, std::abs(o.GetValue()));
-}
-
-TEST(ObserverListTest, StdIteratorRemoveItself) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, true);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(11, a.total);
- EXPECT_EQ(-11, b.total);
- EXPECT_EQ(11, c.total);
- EXPECT_EQ(-11, d.total);
-}
-
-TEST(ObserverListTest, StdIteratorRemoveBefore) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, &b);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(11, a.total);
- EXPECT_EQ(-1, b.total);
- EXPECT_EQ(11, c.total);
- EXPECT_EQ(-11, d.total);
-}
-
-TEST(ObserverListTest, StdIteratorRemoveAfter) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, &c);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(11, a.total);
- EXPECT_EQ(-11, b.total);
- EXPECT_EQ(0, c.total);
- EXPECT_EQ(-11, d.total);
-}
-
-TEST(ObserverListTest, StdIteratorRemoveAfterFront) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, &a);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(1, a.total);
- EXPECT_EQ(-11, b.total);
- EXPECT_EQ(11, c.total);
- EXPECT_EQ(-11, d.total);
-}
-
-TEST(ObserverListTest, StdIteratorRemoveBeforeBack) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, &d);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&d);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(11, a.total);
- EXPECT_EQ(-11, b.total);
- EXPECT_EQ(11, c.total);
- EXPECT_EQ(0, d.total);
-}
-
-TEST(ObserverListTest, StdIteratorRemoveFront) {
- using FooList = ObserverList<Foo>;
- FooList observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, true);
-
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- bool test_disruptor = true;
- for (FooList::iterator i = observer_list.begin(), e = observer_list.end();
- i != e; ++i) {
- i->Observe(1);
- // Check that second call to i->Observe() would crash here.
- if (test_disruptor) {
- EXPECT_FALSE(i.GetCurrent());
- test_disruptor = false;
- }
- }
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(11, a.total);
- EXPECT_EQ(-11, b.total);
- EXPECT_EQ(11, c.total);
- EXPECT_EQ(-11, d.total);
-}
-
-TEST(ObserverListTest, StdIteratorRemoveBack) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, true);
-
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
- observer_list.AddObserver(&disrupter);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- for (auto& o : observer_list)
- o.Observe(10);
-
- EXPECT_EQ(11, a.total);
- EXPECT_EQ(-11, b.total);
- EXPECT_EQ(11, c.total);
- EXPECT_EQ(-11, d.total);
-}
-
-TEST(ObserverListTest, NestedLoop) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1), c(1), d(-1);
- Disrupter disrupter(&observer_list, true);
-
- observer_list.AddObserver(&disrupter);
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- observer_list.AddObserver(&c);
- observer_list.AddObserver(&d);
-
- for (auto& o : observer_list) {
- o.Observe(10);
-
- for (auto& o : observer_list)
- o.Observe(1);
- }
-
- EXPECT_EQ(15, a.total);
- EXPECT_EQ(-15, b.total);
- EXPECT_EQ(15, c.total);
- EXPECT_EQ(-15, d.total);
-}
-
-TEST(ObserverListTest, NonCompactList) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1);
-
- Disrupter disrupter1(&observer_list, true);
- Disrupter disrupter2(&observer_list, true);
-
- // Disrupt itself and another one.
- disrupter1.SetDoomed(&disrupter2);
-
- observer_list.AddObserver(&disrupter1);
- observer_list.AddObserver(&disrupter2);
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
-
- for (auto& o : observer_list) {
- // Get the { nullptr, nullptr, &a, &b } non-compact list
- // on the first inner pass.
- o.Observe(10);
-
- for (auto& o : observer_list)
- o.Observe(1);
- }
-
- EXPECT_EQ(13, a.total);
- EXPECT_EQ(-13, b.total);
-}
-
-TEST(ObserverListTest, BecomesEmptyThanNonEmpty) {
- ObserverList<Foo> observer_list;
- Adder a(1), b(-1);
-
- Disrupter disrupter1(&observer_list, true);
- Disrupter disrupter2(&observer_list, true);
-
- // Disrupt itself and another one.
- disrupter1.SetDoomed(&disrupter2);
-
- observer_list.AddObserver(&disrupter1);
- observer_list.AddObserver(&disrupter2);
-
- bool add_observers = true;
- for (auto& o : observer_list) {
- // Get the { nullptr, nullptr } empty list on the first inner pass.
- o.Observe(10);
-
- for (auto& o : observer_list)
- o.Observe(1);
-
- if (add_observers) {
- observer_list.AddObserver(&a);
- observer_list.AddObserver(&b);
- add_observers = false;
- }
- }
-
- EXPECT_EQ(12, a.total);
- EXPECT_EQ(-12, b.total);
-}
-
-TEST(ObserverListTest, AddObserverInTheLastObserve) {
- using FooList = ObserverList<Foo>;
- FooList observer_list;
-
- AddInObserve<FooList> a(&observer_list);
- Adder b(-1);
-
- a.SetToAdd(&b);
- observer_list.AddObserver(&a);
-
- auto it = observer_list.begin();
- while (it != observer_list.end()) {
- auto& observer = *it;
- // Intentionally increment the iterator before calling Observe(). The
- // ObserverList starts with only one observer, and it == observer_list.end()
- // should be true after the next line.
- ++it;
- // However, the first Observe() call will add a second observer: at this
- // point, it != observer_list.end() should be true, and Observe() should be
- // called on the newly added observer on the next iteration of the loop.
- observer.Observe(10);
- }
-
- EXPECT_EQ(-10, b.total);
-}
-
-class MockLogAssertHandler {
- public:
- MOCK_METHOD4(
- HandleLogAssert,
- void(const char*, int, const base::StringPiece, const base::StringPiece));
-};
-
-#if DCHECK_IS_ON()
-TEST(ObserverListTest, NonReentrantObserverList) {
- using ::testing::_;
-
- ObserverList<Foo, /*check_empty=*/false, /*allow_reentrancy=*/false>
- non_reentrant_observer_list;
- Adder a(1);
- non_reentrant_observer_list.AddObserver(&a);
-
- EXPECT_DCHECK_DEATH({
- for (const Foo& a : non_reentrant_observer_list) {
- for (const Foo& b : non_reentrant_observer_list) {
- std::ignore = a;
- std::ignore = b;
- }
- }
- });
-}
-
-TEST(ObserverListTest, ReentrantObserverList) {
- using ::testing::_;
-
- ReentrantObserverList<Foo> reentrant_observer_list;
- Adder a(1);
- reentrant_observer_list.AddObserver(&a);
- bool passed = false;
- for (const Foo& a : reentrant_observer_list) {
- for (const Foo& b : reentrant_observer_list) {
- std::ignore = a;
- std::ignore = b;
- passed = true;
- }
- }
- EXPECT_TRUE(passed);
-}
-#endif
-
-} // namespace base
diff --git a/base/optional_unittest.cc b/base/optional_unittest.cc
deleted file mode 100644
index 7bdb46b..0000000
--- a/base/optional_unittest.cc
+++ /dev/null
@@ -1,2185 +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/optional.h"
-
-#include <memory>
-#include <set>
-#include <string>
-#include <vector>
-
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-
-namespace base {
-
-namespace {
-
-// Object used to test complex object with Optional<T> in addition of the move
-// semantics.
-class TestObject {
- public:
- enum class State {
- DEFAULT_CONSTRUCTED,
- VALUE_CONSTRUCTED,
- COPY_CONSTRUCTED,
- MOVE_CONSTRUCTED,
- MOVED_FROM,
- COPY_ASSIGNED,
- MOVE_ASSIGNED,
- SWAPPED,
- };
-
- TestObject() : foo_(0), bar_(0.0), state_(State::DEFAULT_CONSTRUCTED) {}
-
- TestObject(int foo, double bar)
- : foo_(foo), bar_(bar), state_(State::VALUE_CONSTRUCTED) {}
-
- TestObject(const TestObject& other)
- : foo_(other.foo_),
- bar_(other.bar_),
- state_(State::COPY_CONSTRUCTED),
- move_ctors_count_(other.move_ctors_count_) {}
-
- TestObject(TestObject&& other)
- : foo_(std::move(other.foo_)),
- bar_(std::move(other.bar_)),
- state_(State::MOVE_CONSTRUCTED),
- move_ctors_count_(other.move_ctors_count_ + 1) {
- other.state_ = State::MOVED_FROM;
- }
-
- TestObject& operator=(const TestObject& other) {
- foo_ = other.foo_;
- bar_ = other.bar_;
- state_ = State::COPY_ASSIGNED;
- move_ctors_count_ = other.move_ctors_count_;
- return *this;
- }
-
- TestObject& operator=(TestObject&& other) {
- foo_ = other.foo_;
- bar_ = other.bar_;
- state_ = State::MOVE_ASSIGNED;
- move_ctors_count_ = other.move_ctors_count_;
- other.state_ = State::MOVED_FROM;
- return *this;
- }
-
- void Swap(TestObject* other) {
- using std::swap;
- swap(foo_, other->foo_);
- swap(bar_, other->bar_);
- swap(move_ctors_count_, other->move_ctors_count_);
- state_ = State::SWAPPED;
- other->state_ = State::SWAPPED;
- }
-
- bool operator==(const TestObject& other) const {
- return std::tie(foo_, bar_) == std::tie(other.foo_, other.bar_);
- }
-
- bool operator!=(const TestObject& other) const { return !(*this == other); }
-
- int foo() const { return foo_; }
- State state() const { return state_; }
- int move_ctors_count() const { return move_ctors_count_; }
-
- private:
- int foo_;
- double bar_;
- State state_;
- int move_ctors_count_ = 0;
-};
-
-// Implementing Swappable concept.
-void swap(TestObject& lhs, TestObject& rhs) {
- lhs.Swap(&rhs);
-}
-
-class NonTriviallyDestructible {
- ~NonTriviallyDestructible() {}
-};
-
-class DeletedDefaultConstructor {
- public:
- DeletedDefaultConstructor() = delete;
- DeletedDefaultConstructor(int foo) : foo_(foo) {}
-
- int foo() const { return foo_; }
-
- private:
- int foo_;
-};
-
-class DeletedCopy {
- public:
- explicit DeletedCopy(int foo) : foo_(foo) {}
- DeletedCopy(const DeletedCopy&) = delete;
- DeletedCopy(DeletedCopy&&) = default;
-
- DeletedCopy& operator=(const DeletedCopy&) = delete;
- DeletedCopy& operator=(DeletedCopy&&) = default;
-
- int foo() const { return foo_; }
-
- private:
- int foo_;
-};
-
-class DeletedMove {
- public:
- explicit DeletedMove(int foo) : foo_(foo) {}
- DeletedMove(const DeletedMove&) = default;
- DeletedMove(DeletedMove&&) = delete;
-
- DeletedMove& operator=(const DeletedMove&) = default;
- DeletedMove& operator=(DeletedMove&&) = delete;
-
- int foo() const { return foo_; }
-
- private:
- int foo_;
-};
-
-class NonTriviallyDestructibleDeletedCopyConstructor {
- public:
- explicit NonTriviallyDestructibleDeletedCopyConstructor(int foo)
- : foo_(foo) {}
- NonTriviallyDestructibleDeletedCopyConstructor(
- const NonTriviallyDestructibleDeletedCopyConstructor&) = delete;
- NonTriviallyDestructibleDeletedCopyConstructor(
- NonTriviallyDestructibleDeletedCopyConstructor&&) = default;
-
- ~NonTriviallyDestructibleDeletedCopyConstructor() {}
-
- int foo() const { return foo_; }
-
- private:
- int foo_;
-};
-
-class DeleteNewOperators {
- public:
- void* operator new(size_t) = delete;
- void* operator new(size_t, void*) = delete;
- void* operator new[](size_t) = delete;
- void* operator new[](size_t, void*) = delete;
-};
-
-} // anonymous namespace
-
-static_assert(std::is_trivially_destructible<Optional<int>>::value,
- "OptionalIsTriviallyDestructible");
-
-static_assert(
- !std::is_trivially_destructible<Optional<NonTriviallyDestructible>>::value,
- "OptionalIsTriviallyDestructible");
-
-static_assert(sizeof(Optional<int>) == sizeof(internal::OptionalBase<int>),
- "internal::{Copy,Move}{Constructible,Assignable} structs "
- "should be 0-sized");
-
-TEST(OptionalTest, DefaultConstructor) {
- {
- constexpr Optional<float> o;
- EXPECT_FALSE(o);
- }
-
- {
- Optional<std::string> o;
- EXPECT_FALSE(o);
- }
-
- {
- Optional<TestObject> o;
- EXPECT_FALSE(o);
- }
-}
-
-TEST(OptionalTest, CopyConstructor) {
- {
- constexpr Optional<float> first(0.1f);
- constexpr Optional<float> other(first);
-
- EXPECT_TRUE(other);
- EXPECT_EQ(other.value(), 0.1f);
- EXPECT_EQ(first, other);
- }
-
- {
- Optional<std::string> first("foo");
- Optional<std::string> other(first);
-
- EXPECT_TRUE(other);
- EXPECT_EQ(other.value(), "foo");
- EXPECT_EQ(first, other);
- }
-
- {
- const Optional<std::string> first("foo");
- Optional<std::string> other(first);
-
- EXPECT_TRUE(other);
- EXPECT_EQ(other.value(), "foo");
- EXPECT_EQ(first, other);
- }
-
- {
- Optional<TestObject> first(TestObject(3, 0.1));
- Optional<TestObject> other(first);
-
- EXPECT_TRUE(!!other);
- EXPECT_TRUE(other.value() == TestObject(3, 0.1));
- EXPECT_TRUE(first == other);
- }
-}
-
-TEST(OptionalTest, ValueConstructor) {
- {
- constexpr float value = 0.1f;
- constexpr Optional<float> o(value);
-
- EXPECT_TRUE(o);
- EXPECT_EQ(value, o.value());
- }
-
- {
- std::string value("foo");
- Optional<std::string> o(value);
-
- EXPECT_TRUE(o);
- EXPECT_EQ(value, o.value());
- }
-
- {
- TestObject value(3, 0.1);
- Optional<TestObject> o(value);
-
- EXPECT_TRUE(o);
- EXPECT_EQ(TestObject::State::COPY_CONSTRUCTED, o->state());
- EXPECT_EQ(value, o.value());
- }
-}
-
-TEST(OptionalTest, MoveConstructor) {
- {
- constexpr Optional<float> first(0.1f);
- constexpr Optional<float> second(std::move(first));
-
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(second.value(), 0.1f);
-
- EXPECT_TRUE(first.has_value());
- }
-
- {
- Optional<std::string> first("foo");
- Optional<std::string> second(std::move(first));
-
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ("foo", second.value());
-
- EXPECT_TRUE(first.has_value());
- }
-
- {
- Optional<TestObject> first(TestObject(3, 0.1));
- Optional<TestObject> second(std::move(first));
-
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, second->state());
- EXPECT_TRUE(TestObject(3, 0.1) == second.value());
-
- EXPECT_TRUE(first.has_value());
- EXPECT_EQ(TestObject::State::MOVED_FROM, first->state());
- }
-
- // Even if copy constructor is deleted, move constructor needs to work.
- // Note that it couldn't be constexpr.
- {
- Optional<DeletedCopy> first(in_place, 42);
- Optional<DeletedCopy> second(std::move(first));
-
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(42, second->foo());
-
- EXPECT_TRUE(first.has_value());
- }
-
- {
- Optional<DeletedMove> first(in_place, 42);
- Optional<DeletedMove> second(std::move(first));
-
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(42, second->foo());
-
- EXPECT_TRUE(first.has_value());
- }
-
- {
- Optional<NonTriviallyDestructibleDeletedCopyConstructor> first(in_place,
- 42);
- Optional<NonTriviallyDestructibleDeletedCopyConstructor> second(
- std::move(first));
-
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(42, second->foo());
-
- EXPECT_TRUE(first.has_value());
- }
-}
-
-TEST(OptionalTest, MoveValueConstructor) {
- {
- constexpr float value = 0.1f;
- constexpr Optional<float> o(std::move(value));
-
- EXPECT_TRUE(o);
- EXPECT_EQ(0.1f, o.value());
- }
-
- {
- float value = 0.1f;
- Optional<float> o(std::move(value));
-
- EXPECT_TRUE(o);
- EXPECT_EQ(0.1f, o.value());
- }
-
- {
- std::string value("foo");
- Optional<std::string> o(std::move(value));
-
- EXPECT_TRUE(o);
- EXPECT_EQ("foo", o.value());
- }
-
- {
- TestObject value(3, 0.1);
- Optional<TestObject> o(std::move(value));
-
- EXPECT_TRUE(o);
- EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, o->state());
- EXPECT_EQ(TestObject(3, 0.1), o.value());
- }
-}
-
-TEST(OptionalTest, ConvertingCopyConstructor) {
- {
- Optional<int> first(1);
- Optional<double> second(first);
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(1.0, second.value());
- }
-
- // Make sure explicit is not marked for convertible case.
- {
- Optional<int> o(1);
- ignore_result<Optional<double>>(o);
- }
-}
-
-TEST(OptionalTest, ConvertingMoveConstructor) {
- {
- Optional<int> first(1);
- Optional<double> second(std::move(first));
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(1.0, second.value());
- }
-
- // Make sure explicit is not marked for convertible case.
- {
- Optional<int> o(1);
- ignore_result<Optional<double>>(std::move(o));
- }
-
- {
- class Test1 {
- public:
- explicit Test1(int foo) : foo_(foo) {}
-
- int foo() const { return foo_; }
-
- private:
- int foo_;
- };
-
- // Not copyable but convertible from Test1.
- class Test2 {
- public:
- Test2(const Test2&) = delete;
- explicit Test2(Test1&& other) : bar_(other.foo()) {}
-
- double bar() const { return bar_; }
-
- private:
- double bar_;
- };
-
- Optional<Test1> first(in_place, 42);
- Optional<Test2> second(std::move(first));
- EXPECT_TRUE(second.has_value());
- EXPECT_EQ(42.0, second->bar());
- }
-}
-
-TEST(OptionalTest, ConstructorForwardArguments) {
- {
- constexpr Optional<float> a(base::in_place, 0.1f);
- EXPECT_TRUE(a);
- EXPECT_EQ(0.1f, a.value());
- }
-
- {
- Optional<float> a(base::in_place, 0.1f);
- EXPECT_TRUE(a);
- EXPECT_EQ(0.1f, a.value());
- }
-
- {
- Optional<std::string> a(base::in_place, "foo");
- EXPECT_TRUE(a);
- EXPECT_EQ("foo", a.value());
- }
-
- {
- Optional<TestObject> a(base::in_place, 0, 0.1);
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(TestObject(0, 0.1) == a.value());
- }
-}
-
-TEST(OptionalTest, ConstructorForwardInitListAndArguments) {
- {
- Optional<std::vector<int>> opt(in_place, {3, 1});
- EXPECT_TRUE(opt);
- EXPECT_THAT(*opt, ElementsAre(3, 1));
- EXPECT_EQ(2u, opt->size());
- }
-
- {
- Optional<std::vector<int>> opt(in_place, {3, 1}, std::allocator<int>());
- EXPECT_TRUE(opt);
- EXPECT_THAT(*opt, ElementsAre(3, 1));
- EXPECT_EQ(2u, opt->size());
- }
-}
-
-TEST(OptionalTest, ForwardConstructor) {
- {
- Optional<double> a(1);
- EXPECT_TRUE(a.has_value());
- EXPECT_EQ(1.0, a.value());
- }
-
- // Test that default type of 'U' is value_type.
- {
- struct TestData {
- int a;
- double b;
- bool c;
- };
-
- Optional<TestData> a({1, 2.0, true});
- EXPECT_TRUE(a.has_value());
- EXPECT_EQ(1, a->a);
- EXPECT_EQ(2.0, a->b);
- EXPECT_TRUE(a->c);
- }
-
- // If T has a constructor with a param Optional<U>, and another ctor with a
- // param U, then T(Optional<U>) should be used for Optional<T>(Optional<U>)
- // constructor.
- {
- enum class ParamType {
- DEFAULT_CONSTRUCTED,
- COPY_CONSTRUCTED,
- MOVE_CONSTRUCTED,
- INT,
- IN_PLACE,
- OPTIONAL_INT,
- };
- struct Test {
- Test() : param_type(ParamType::DEFAULT_CONSTRUCTED) {}
- Test(const Test& param) : param_type(ParamType::COPY_CONSTRUCTED) {}
- Test(Test&& param) : param_type(ParamType::MOVE_CONSTRUCTED) {}
- explicit Test(int param) : param_type(ParamType::INT) {}
- explicit Test(in_place_t param) : param_type(ParamType::IN_PLACE) {}
- explicit Test(Optional<int> param)
- : param_type(ParamType::OPTIONAL_INT) {}
-
- ParamType param_type;
- };
-
- // Overload resolution with copy-conversion constructor.
- {
- const Optional<int> arg(in_place, 1);
- Optional<Test> testee(arg);
- EXPECT_EQ(ParamType::OPTIONAL_INT, testee->param_type);
- }
-
- // Overload resolution with move conversion constructor.
- {
- Optional<Test> testee(Optional<int>(in_place, 1));
- EXPECT_EQ(ParamType::OPTIONAL_INT, testee->param_type);
- }
-
- // Default constructor should be used.
- {
- Optional<Test> testee(in_place);
- EXPECT_EQ(ParamType::DEFAULT_CONSTRUCTED, testee->param_type);
- }
- }
-
- {
- struct Test {
- Test(int a) {} // NOLINT(runtime/explicit)
- };
- // If T is convertible from U, it is not marked as explicit.
- static_assert(std::is_convertible<int, Test>::value,
- "Int should be convertible to Test.");
- ([](Optional<Test> param) {})(1);
- }
-}
-
-TEST(OptionalTest, NulloptConstructor) {
- constexpr Optional<int> a(base::nullopt);
- EXPECT_FALSE(a);
-}
-
-TEST(OptionalTest, AssignValue) {
- {
- Optional<float> a;
- EXPECT_FALSE(a);
- a = 0.1f;
- EXPECT_TRUE(a);
-
- Optional<float> b(0.1f);
- EXPECT_TRUE(a == b);
- }
-
- {
- Optional<std::string> a;
- EXPECT_FALSE(a);
- a = std::string("foo");
- EXPECT_TRUE(a);
-
- Optional<std::string> b(std::string("foo"));
- EXPECT_EQ(a, b);
- }
-
- {
- Optional<TestObject> a;
- EXPECT_FALSE(!!a);
- a = TestObject(3, 0.1);
- EXPECT_TRUE(!!a);
-
- Optional<TestObject> b(TestObject(3, 0.1));
- EXPECT_TRUE(a == b);
- }
-
- {
- Optional<TestObject> a = TestObject(4, 1.0);
- EXPECT_TRUE(!!a);
- a = TestObject(3, 0.1);
- EXPECT_TRUE(!!a);
-
- Optional<TestObject> b(TestObject(3, 0.1));
- EXPECT_TRUE(a == b);
- }
-}
-
-TEST(OptionalTest, AssignObject) {
- {
- Optional<float> a;
- Optional<float> b(0.1f);
- a = b;
-
- EXPECT_TRUE(a);
- EXPECT_EQ(a.value(), 0.1f);
- EXPECT_EQ(a, b);
- }
-
- {
- Optional<std::string> a;
- Optional<std::string> b("foo");
- a = b;
-
- EXPECT_TRUE(a);
- EXPECT_EQ(a.value(), "foo");
- EXPECT_EQ(a, b);
- }
-
- {
- Optional<TestObject> a;
- Optional<TestObject> b(TestObject(3, 0.1));
- a = b;
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(a.value() == TestObject(3, 0.1));
- EXPECT_TRUE(a == b);
- }
-
- {
- Optional<TestObject> a(TestObject(4, 1.0));
- Optional<TestObject> b(TestObject(3, 0.1));
- a = b;
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(a.value() == TestObject(3, 0.1));
- EXPECT_TRUE(a == b);
- }
-
- {
- Optional<DeletedMove> a(in_place, 42);
- Optional<DeletedMove> b;
- b = a;
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(a->foo(), b->foo());
- }
-
- {
- Optional<DeletedMove> a(in_place, 42);
- Optional<DeletedMove> b(in_place, 1);
- b = a;
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(a->foo(), b->foo());
- }
-
- // Converting assignment.
- {
- Optional<int> a(in_place, 1);
- Optional<double> b;
- b = a;
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(1, a.value());
- EXPECT_EQ(1.0, b.value());
- }
-
- {
- Optional<int> a(in_place, 42);
- Optional<double> b(in_place, 1);
- b = a;
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(42, a.value());
- EXPECT_EQ(42.0, b.value());
- }
-
- {
- Optional<int> a;
- Optional<double> b(in_place, 1);
- b = a;
- EXPECT_FALSE(!!a);
- EXPECT_FALSE(!!b);
- }
-}
-
-TEST(OptionalTest, AssignObject_rvalue) {
- {
- Optional<float> a;
- Optional<float> b(0.1f);
- a = std::move(b);
-
- EXPECT_TRUE(a);
- EXPECT_TRUE(b);
- EXPECT_EQ(0.1f, a.value());
- }
-
- {
- Optional<std::string> a;
- Optional<std::string> b("foo");
- a = std::move(b);
-
- EXPECT_TRUE(a);
- EXPECT_TRUE(b);
- EXPECT_EQ("foo", a.value());
- }
-
- {
- Optional<TestObject> a;
- Optional<TestObject> b(TestObject(3, 0.1));
- a = std::move(b);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(TestObject(3, 0.1) == a.value());
-
- EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED, a->state());
- EXPECT_EQ(TestObject::State::MOVED_FROM, b->state());
- }
-
- {
- Optional<TestObject> a(TestObject(4, 1.0));
- Optional<TestObject> b(TestObject(3, 0.1));
- a = std::move(b);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(TestObject(3, 0.1) == a.value());
-
- EXPECT_EQ(TestObject::State::MOVE_ASSIGNED, a->state());
- EXPECT_EQ(TestObject::State::MOVED_FROM, b->state());
- }
-
- {
- Optional<DeletedMove> a(in_place, 42);
- Optional<DeletedMove> b;
- b = std::move(a);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(42, b->foo());
- }
-
- {
- Optional<DeletedMove> a(in_place, 42);
- Optional<DeletedMove> b(in_place, 1);
- b = std::move(a);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(42, b->foo());
- }
-
- // Converting assignment.
- {
- Optional<int> a(in_place, 1);
- Optional<double> b;
- b = std::move(a);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(1.0, b.value());
- }
-
- {
- Optional<int> a(in_place, 42);
- Optional<double> b(in_place, 1);
- b = std::move(a);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(42.0, b.value());
- }
-
- {
- Optional<int> a;
- Optional<double> b(in_place, 1);
- b = std::move(a);
-
- EXPECT_FALSE(!!a);
- EXPECT_FALSE(!!b);
- }
-}
-
-TEST(OptionalTest, AssignNull) {
- {
- Optional<float> a(0.1f);
- Optional<float> b(0.2f);
- a = base::nullopt;
- b = base::nullopt;
- EXPECT_EQ(a, b);
- }
-
- {
- Optional<std::string> a("foo");
- Optional<std::string> b("bar");
- a = base::nullopt;
- b = base::nullopt;
- EXPECT_EQ(a, b);
- }
-
- {
- Optional<TestObject> a(TestObject(3, 0.1));
- Optional<TestObject> b(TestObject(4, 1.0));
- a = base::nullopt;
- b = base::nullopt;
- EXPECT_TRUE(a == b);
- }
-}
-
-TEST(OptionalTest, AssignOverload) {
- struct Test1 {
- enum class State {
- CONSTRUCTED,
- MOVED,
- };
- State state = State::CONSTRUCTED;
- };
-
- // Here, Optional<Test2> can be assigned from Optioanl<Test1>.
- // In case of move, marks MOVED to Test1 instance.
- struct Test2 {
- enum class State {
- DEFAULT_CONSTRUCTED,
- COPY_CONSTRUCTED_FROM_TEST1,
- MOVE_CONSTRUCTED_FROM_TEST1,
- COPY_ASSIGNED_FROM_TEST1,
- MOVE_ASSIGNED_FROM_TEST1,
- };
-
- Test2() = default;
- explicit Test2(const Test1& test1)
- : state(State::COPY_CONSTRUCTED_FROM_TEST1) {}
- explicit Test2(Test1&& test1) : state(State::MOVE_CONSTRUCTED_FROM_TEST1) {
- test1.state = Test1::State::MOVED;
- }
- Test2& operator=(const Test1& test1) {
- state = State::COPY_ASSIGNED_FROM_TEST1;
- return *this;
- }
- Test2& operator=(Test1&& test1) {
- state = State::MOVE_ASSIGNED_FROM_TEST1;
- test1.state = Test1::State::MOVED;
- return *this;
- }
-
- State state = State::DEFAULT_CONSTRUCTED;
- };
-
- {
- Optional<Test1> a(in_place);
- Optional<Test2> b;
-
- b = a;
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::CONSTRUCTED, a->state);
- EXPECT_EQ(Test2::State::COPY_CONSTRUCTED_FROM_TEST1, b->state);
- }
-
- {
- Optional<Test1> a(in_place);
- Optional<Test2> b(in_place);
-
- b = a;
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::CONSTRUCTED, a->state);
- EXPECT_EQ(Test2::State::COPY_ASSIGNED_FROM_TEST1, b->state);
- }
-
- {
- Optional<Test1> a(in_place);
- Optional<Test2> b;
-
- b = std::move(a);
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::MOVED, a->state);
- EXPECT_EQ(Test2::State::MOVE_CONSTRUCTED_FROM_TEST1, b->state);
- }
-
- {
- Optional<Test1> a(in_place);
- Optional<Test2> b(in_place);
-
- b = std::move(a);
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::MOVED, a->state);
- EXPECT_EQ(Test2::State::MOVE_ASSIGNED_FROM_TEST1, b->state);
- }
-
- // Similar to Test2, but Test3 also has copy/move ctor and assign operators
- // from Optional<Test1>, too. In this case, for a = b where a is
- // Optional<Test3> and b is Optional<Test1>,
- // Optional<T>::operator=(U&&) where U is Optional<Test1> should be used
- // rather than Optional<T>::operator=(Optional<U>&&) where U is Test1.
- struct Test3 {
- enum class State {
- DEFAULT_CONSTRUCTED,
- COPY_CONSTRUCTED_FROM_TEST1,
- MOVE_CONSTRUCTED_FROM_TEST1,
- COPY_CONSTRUCTED_FROM_OPTIONAL_TEST1,
- MOVE_CONSTRUCTED_FROM_OPTIONAL_TEST1,
- COPY_ASSIGNED_FROM_TEST1,
- MOVE_ASSIGNED_FROM_TEST1,
- COPY_ASSIGNED_FROM_OPTIONAL_TEST1,
- MOVE_ASSIGNED_FROM_OPTIONAL_TEST1,
- };
-
- Test3() = default;
- explicit Test3(const Test1& test1)
- : state(State::COPY_CONSTRUCTED_FROM_TEST1) {}
- explicit Test3(Test1&& test1) : state(State::MOVE_CONSTRUCTED_FROM_TEST1) {
- test1.state = Test1::State::MOVED;
- }
- explicit Test3(const Optional<Test1>& test1)
- : state(State::COPY_CONSTRUCTED_FROM_OPTIONAL_TEST1) {}
- explicit Test3(Optional<Test1>&& test1)
- : state(State::MOVE_CONSTRUCTED_FROM_OPTIONAL_TEST1) {
- // In the following senarios, given |test1| should always have value.
- DCHECK(test1.has_value());
- test1->state = Test1::State::MOVED;
- }
- Test3& operator=(const Test1& test1) {
- state = State::COPY_ASSIGNED_FROM_TEST1;
- return *this;
- }
- Test3& operator=(Test1&& test1) {
- state = State::MOVE_ASSIGNED_FROM_TEST1;
- test1.state = Test1::State::MOVED;
- return *this;
- }
- Test3& operator=(const Optional<Test1>& test1) {
- state = State::COPY_ASSIGNED_FROM_OPTIONAL_TEST1;
- return *this;
- }
- Test3& operator=(Optional<Test1>&& test1) {
- state = State::MOVE_ASSIGNED_FROM_OPTIONAL_TEST1;
- // In the following senarios, given |test1| should always have value.
- DCHECK(test1.has_value());
- test1->state = Test1::State::MOVED;
- return *this;
- }
-
- State state = State::DEFAULT_CONSTRUCTED;
- };
-
- {
- Optional<Test1> a(in_place);
- Optional<Test3> b;
-
- b = a;
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::CONSTRUCTED, a->state);
- EXPECT_EQ(Test3::State::COPY_CONSTRUCTED_FROM_OPTIONAL_TEST1, b->state);
- }
-
- {
- Optional<Test1> a(in_place);
- Optional<Test3> b(in_place);
-
- b = a;
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::CONSTRUCTED, a->state);
- EXPECT_EQ(Test3::State::COPY_ASSIGNED_FROM_OPTIONAL_TEST1, b->state);
- }
-
- {
- Optional<Test1> a(in_place);
- Optional<Test3> b;
-
- b = std::move(a);
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::MOVED, a->state);
- EXPECT_EQ(Test3::State::MOVE_CONSTRUCTED_FROM_OPTIONAL_TEST1, b->state);
- }
-
- {
- Optional<Test1> a(in_place);
- Optional<Test3> b(in_place);
-
- b = std::move(a);
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_EQ(Test1::State::MOVED, a->state);
- EXPECT_EQ(Test3::State::MOVE_ASSIGNED_FROM_OPTIONAL_TEST1, b->state);
- }
-}
-
-TEST(OptionalTest, OperatorStar) {
- {
- Optional<float> a(0.1f);
- EXPECT_EQ(a.value(), *a);
- }
-
- {
- Optional<std::string> a("foo");
- EXPECT_EQ(a.value(), *a);
- }
-
- {
- Optional<TestObject> a(TestObject(3, 0.1));
- EXPECT_EQ(a.value(), *a);
- }
-}
-
-TEST(OptionalTest, OperatorStar_rvalue) {
- EXPECT_EQ(0.1f, *Optional<float>(0.1f));
- EXPECT_EQ(std::string("foo"), *Optional<std::string>("foo"));
- EXPECT_TRUE(TestObject(3, 0.1) == *Optional<TestObject>(TestObject(3, 0.1)));
-}
-
-TEST(OptionalTest, OperatorArrow) {
- Optional<TestObject> a(TestObject(3, 0.1));
- EXPECT_EQ(a->foo(), 3);
-}
-
-TEST(OptionalTest, Value_rvalue) {
- EXPECT_EQ(0.1f, Optional<float>(0.1f).value());
- EXPECT_EQ(std::string("foo"), Optional<std::string>("foo").value());
- EXPECT_TRUE(TestObject(3, 0.1) ==
- Optional<TestObject>(TestObject(3, 0.1)).value());
-}
-
-TEST(OptionalTest, ValueOr) {
- {
- Optional<float> a;
- EXPECT_EQ(0.0f, a.value_or(0.0f));
-
- a = 0.1f;
- EXPECT_EQ(0.1f, a.value_or(0.0f));
-
- a = base::nullopt;
- EXPECT_EQ(0.0f, a.value_or(0.0f));
- }
-
- // value_or() can be constexpr.
- {
- constexpr Optional<int> a(in_place, 1);
- constexpr int value = a.value_or(10);
- EXPECT_EQ(1, value);
- }
- {
- constexpr Optional<int> a;
- constexpr int value = a.value_or(10);
- EXPECT_EQ(10, value);
- }
-
- {
- Optional<std::string> a;
- EXPECT_EQ("bar", a.value_or("bar"));
-
- a = std::string("foo");
- EXPECT_EQ(std::string("foo"), a.value_or("bar"));
-
- a = base::nullopt;
- EXPECT_EQ(std::string("bar"), a.value_or("bar"));
- }
-
- {
- Optional<TestObject> a;
- EXPECT_TRUE(a.value_or(TestObject(1, 0.3)) == TestObject(1, 0.3));
-
- a = TestObject(3, 0.1);
- EXPECT_TRUE(a.value_or(TestObject(1, 0.3)) == TestObject(3, 0.1));
-
- a = base::nullopt;
- EXPECT_TRUE(a.value_or(TestObject(1, 0.3)) == TestObject(1, 0.3));
- }
-}
-
-TEST(OptionalTest, Swap_bothNoValue) {
- Optional<TestObject> a, b;
- a.swap(b);
-
- EXPECT_FALSE(a);
- EXPECT_FALSE(b);
- EXPECT_TRUE(TestObject(42, 0.42) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(42, 0.42) == b.value_or(TestObject(42, 0.42)));
-}
-
-TEST(OptionalTest, Swap_inHasValue) {
- Optional<TestObject> a(TestObject(1, 0.3));
- Optional<TestObject> b;
- a.swap(b);
-
- EXPECT_FALSE(a);
-
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(TestObject(42, 0.42) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(1, 0.3) == b.value_or(TestObject(42, 0.42)));
-}
-
-TEST(OptionalTest, Swap_outHasValue) {
- Optional<TestObject> a;
- Optional<TestObject> b(TestObject(1, 0.3));
- a.swap(b);
-
- EXPECT_TRUE(!!a);
- EXPECT_FALSE(!!b);
- EXPECT_TRUE(TestObject(1, 0.3) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(42, 0.42) == b.value_or(TestObject(42, 0.42)));
-}
-
-TEST(OptionalTest, Swap_bothValue) {
- Optional<TestObject> a(TestObject(0, 0.1));
- Optional<TestObject> b(TestObject(1, 0.3));
- a.swap(b);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(TestObject(1, 0.3) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(0, 0.1) == b.value_or(TestObject(42, 0.42)));
- EXPECT_EQ(TestObject::State::SWAPPED, a->state());
- EXPECT_EQ(TestObject::State::SWAPPED, b->state());
-}
-
-TEST(OptionalTest, Emplace) {
- {
- Optional<float> a(0.1f);
- EXPECT_EQ(0.3f, a.emplace(0.3f));
-
- EXPECT_TRUE(a);
- EXPECT_EQ(0.3f, a.value());
- }
-
- {
- Optional<std::string> a("foo");
- EXPECT_EQ("bar", a.emplace("bar"));
-
- EXPECT_TRUE(a);
- EXPECT_EQ("bar", a.value());
- }
-
- {
- Optional<TestObject> a(TestObject(0, 0.1));
- EXPECT_EQ(TestObject(1, 0.2), a.emplace(TestObject(1, 0.2)));
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(TestObject(1, 0.2) == a.value());
- }
-
- {
- Optional<std::vector<int>> a;
- auto& ref = a.emplace({2, 3});
- static_assert(std::is_same<std::vector<int>&, decltype(ref)>::value, "");
- EXPECT_TRUE(a);
- EXPECT_THAT(*a, ElementsAre(2, 3));
- EXPECT_EQ(&ref, &*a);
- }
-
- {
- Optional<std::vector<int>> a;
- auto& ref = a.emplace({4, 5}, std::allocator<int>());
- static_assert(std::is_same<std::vector<int>&, decltype(ref)>::value, "");
- EXPECT_TRUE(a);
- EXPECT_THAT(*a, ElementsAre(4, 5));
- EXPECT_EQ(&ref, &*a);
- }
-}
-
-TEST(OptionalTest, Equals_TwoEmpty) {
- Optional<int> a;
- Optional<int> b;
-
- EXPECT_TRUE(a == b);
-}
-
-TEST(OptionalTest, Equals_TwoEquals) {
- Optional<int> a(1);
- Optional<int> b(1);
-
- EXPECT_TRUE(a == b);
-}
-
-TEST(OptionalTest, Equals_OneEmpty) {
- Optional<int> a;
- Optional<int> b(1);
-
- EXPECT_FALSE(a == b);
-}
-
-TEST(OptionalTest, Equals_TwoDifferent) {
- Optional<int> a(0);
- Optional<int> b(1);
-
- EXPECT_FALSE(a == b);
-}
-
-TEST(OptionalTest, Equals_DifferentType) {
- Optional<int> a(0);
- Optional<double> b(0);
-
- EXPECT_TRUE(a == b);
-}
-
-TEST(OptionalTest, NotEquals_TwoEmpty) {
- Optional<int> a;
- Optional<int> b;
-
- EXPECT_FALSE(a != b);
-}
-
-TEST(OptionalTest, NotEquals_TwoEquals) {
- Optional<int> a(1);
- Optional<int> b(1);
-
- EXPECT_FALSE(a != b);
-}
-
-TEST(OptionalTest, NotEquals_OneEmpty) {
- Optional<int> a;
- Optional<int> b(1);
-
- EXPECT_TRUE(a != b);
-}
-
-TEST(OptionalTest, NotEquals_TwoDifferent) {
- Optional<int> a(0);
- Optional<int> b(1);
-
- EXPECT_TRUE(a != b);
-}
-
-TEST(OptionalTest, NotEquals_DifferentType) {
- Optional<int> a(0);
- Optional<double> b(0.0);
-
- EXPECT_FALSE(a != b);
-}
-
-TEST(OptionalTest, Less_LeftEmpty) {
- Optional<int> l;
- Optional<int> r(1);
-
- EXPECT_TRUE(l < r);
-}
-
-TEST(OptionalTest, Less_RightEmpty) {
- Optional<int> l(1);
- Optional<int> r;
-
- EXPECT_FALSE(l < r);
-}
-
-TEST(OptionalTest, Less_BothEmpty) {
- Optional<int> l;
- Optional<int> r;
-
- EXPECT_FALSE(l < r);
-}
-
-TEST(OptionalTest, Less_BothValues) {
- {
- Optional<int> l(1);
- Optional<int> r(2);
-
- EXPECT_TRUE(l < r);
- }
- {
- Optional<int> l(2);
- Optional<int> r(1);
-
- EXPECT_FALSE(l < r);
- }
- {
- Optional<int> l(1);
- Optional<int> r(1);
-
- EXPECT_FALSE(l < r);
- }
-}
-
-TEST(OptionalTest, Less_DifferentType) {
- Optional<int> l(1);
- Optional<double> r(2.0);
-
- EXPECT_TRUE(l < r);
-}
-
-TEST(OptionalTest, LessEq_LeftEmpty) {
- Optional<int> l;
- Optional<int> r(1);
-
- EXPECT_TRUE(l <= r);
-}
-
-TEST(OptionalTest, LessEq_RightEmpty) {
- Optional<int> l(1);
- Optional<int> r;
-
- EXPECT_FALSE(l <= r);
-}
-
-TEST(OptionalTest, LessEq_BothEmpty) {
- Optional<int> l;
- Optional<int> r;
-
- EXPECT_TRUE(l <= r);
-}
-
-TEST(OptionalTest, LessEq_BothValues) {
- {
- Optional<int> l(1);
- Optional<int> r(2);
-
- EXPECT_TRUE(l <= r);
- }
- {
- Optional<int> l(2);
- Optional<int> r(1);
-
- EXPECT_FALSE(l <= r);
- }
- {
- Optional<int> l(1);
- Optional<int> r(1);
-
- EXPECT_TRUE(l <= r);
- }
-}
-
-TEST(OptionalTest, LessEq_DifferentType) {
- Optional<int> l(1);
- Optional<double> r(2.0);
-
- EXPECT_TRUE(l <= r);
-}
-
-TEST(OptionalTest, Greater_BothEmpty) {
- Optional<int> l;
- Optional<int> r;
-
- EXPECT_FALSE(l > r);
-}
-
-TEST(OptionalTest, Greater_LeftEmpty) {
- Optional<int> l;
- Optional<int> r(1);
-
- EXPECT_FALSE(l > r);
-}
-
-TEST(OptionalTest, Greater_RightEmpty) {
- Optional<int> l(1);
- Optional<int> r;
-
- EXPECT_TRUE(l > r);
-}
-
-TEST(OptionalTest, Greater_BothValue) {
- {
- Optional<int> l(1);
- Optional<int> r(2);
-
- EXPECT_FALSE(l > r);
- }
- {
- Optional<int> l(2);
- Optional<int> r(1);
-
- EXPECT_TRUE(l > r);
- }
- {
- Optional<int> l(1);
- Optional<int> r(1);
-
- EXPECT_FALSE(l > r);
- }
-}
-
-TEST(OptionalTest, Greater_DifferentType) {
- Optional<int> l(1);
- Optional<double> r(2.0);
-
- EXPECT_FALSE(l > r);
-}
-
-TEST(OptionalTest, GreaterEq_BothEmpty) {
- Optional<int> l;
- Optional<int> r;
-
- EXPECT_TRUE(l >= r);
-}
-
-TEST(OptionalTest, GreaterEq_LeftEmpty) {
- Optional<int> l;
- Optional<int> r(1);
-
- EXPECT_FALSE(l >= r);
-}
-
-TEST(OptionalTest, GreaterEq_RightEmpty) {
- Optional<int> l(1);
- Optional<int> r;
-
- EXPECT_TRUE(l >= r);
-}
-
-TEST(OptionalTest, GreaterEq_BothValue) {
- {
- Optional<int> l(1);
- Optional<int> r(2);
-
- EXPECT_FALSE(l >= r);
- }
- {
- Optional<int> l(2);
- Optional<int> r(1);
-
- EXPECT_TRUE(l >= r);
- }
- {
- Optional<int> l(1);
- Optional<int> r(1);
-
- EXPECT_TRUE(l >= r);
- }
-}
-
-TEST(OptionalTest, GreaterEq_DifferentType) {
- Optional<int> l(1);
- Optional<double> r(2.0);
-
- EXPECT_FALSE(l >= r);
-}
-
-TEST(OptionalTest, OptNullEq) {
- {
- Optional<int> opt;
- EXPECT_TRUE(opt == base::nullopt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(opt == base::nullopt);
- }
-}
-
-TEST(OptionalTest, NullOptEq) {
- {
- Optional<int> opt;
- EXPECT_TRUE(base::nullopt == opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(base::nullopt == opt);
- }
-}
-
-TEST(OptionalTest, OptNullNotEq) {
- {
- Optional<int> opt;
- EXPECT_FALSE(opt != base::nullopt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(opt != base::nullopt);
- }
-}
-
-TEST(OptionalTest, NullOptNotEq) {
- {
- Optional<int> opt;
- EXPECT_FALSE(base::nullopt != opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(base::nullopt != opt);
- }
-}
-
-TEST(OptionalTest, OptNullLower) {
- {
- Optional<int> opt;
- EXPECT_FALSE(opt < base::nullopt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(opt < base::nullopt);
- }
-}
-
-TEST(OptionalTest, NullOptLower) {
- {
- Optional<int> opt;
- EXPECT_FALSE(base::nullopt < opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(base::nullopt < opt);
- }
-}
-
-TEST(OptionalTest, OptNullLowerEq) {
- {
- Optional<int> opt;
- EXPECT_TRUE(opt <= base::nullopt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(opt <= base::nullopt);
- }
-}
-
-TEST(OptionalTest, NullOptLowerEq) {
- {
- Optional<int> opt;
- EXPECT_TRUE(base::nullopt <= opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(base::nullopt <= opt);
- }
-}
-
-TEST(OptionalTest, OptNullGreater) {
- {
- Optional<int> opt;
- EXPECT_FALSE(opt > base::nullopt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(opt > base::nullopt);
- }
-}
-
-TEST(OptionalTest, NullOptGreater) {
- {
- Optional<int> opt;
- EXPECT_FALSE(base::nullopt > opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(base::nullopt > opt);
- }
-}
-
-TEST(OptionalTest, OptNullGreaterEq) {
- {
- Optional<int> opt;
- EXPECT_TRUE(opt >= base::nullopt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(opt >= base::nullopt);
- }
-}
-
-TEST(OptionalTest, NullOptGreaterEq) {
- {
- Optional<int> opt;
- EXPECT_TRUE(base::nullopt >= opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(base::nullopt >= opt);
- }
-}
-
-TEST(OptionalTest, ValueEq_Empty) {
- Optional<int> opt;
- EXPECT_FALSE(opt == 1);
-}
-
-TEST(OptionalTest, ValueEq_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_FALSE(opt == 1);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(opt == 1);
- }
-}
-
-TEST(OptionalTest, ValueEq_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(opt == 0.0);
-}
-
-TEST(OptionalTest, EqValue_Empty) {
- Optional<int> opt;
- EXPECT_FALSE(1 == opt);
-}
-
-TEST(OptionalTest, EqValue_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_FALSE(1 == opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(1 == opt);
- }
-}
-
-TEST(OptionalTest, EqValue_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(0.0 == opt);
-}
-
-TEST(OptionalTest, ValueNotEq_Empty) {
- Optional<int> opt;
- EXPECT_TRUE(opt != 1);
-}
-
-TEST(OptionalTest, ValueNotEq_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_TRUE(opt != 1);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(opt != 1);
- }
-}
-
-TEST(OPtionalTest, ValueNotEq_DifferentType) {
- Optional<int> opt(0);
- EXPECT_FALSE(opt != 0.0);
-}
-
-TEST(OptionalTest, NotEqValue_Empty) {
- Optional<int> opt;
- EXPECT_TRUE(1 != opt);
-}
-
-TEST(OptionalTest, NotEqValue_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_TRUE(1 != opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(1 != opt);
- }
-}
-
-TEST(OptionalTest, NotEqValue_DifferentType) {
- Optional<int> opt(0);
- EXPECT_FALSE(0.0 != opt);
-}
-
-TEST(OptionalTest, ValueLess_Empty) {
- Optional<int> opt;
- EXPECT_TRUE(opt < 1);
-}
-
-TEST(OptionalTest, ValueLess_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_TRUE(opt < 1);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(opt < 1);
- }
- {
- Optional<int> opt(2);
- EXPECT_FALSE(opt < 1);
- }
-}
-
-TEST(OPtionalTest, ValueLess_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(opt < 1.0);
-}
-
-TEST(OptionalTest, LessValue_Empty) {
- Optional<int> opt;
- EXPECT_FALSE(1 < opt);
-}
-
-TEST(OptionalTest, LessValue_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_FALSE(1 < opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(1 < opt);
- }
- {
- Optional<int> opt(2);
- EXPECT_TRUE(1 < opt);
- }
-}
-
-TEST(OptionalTest, LessValue_DifferentType) {
- Optional<int> opt(0);
- EXPECT_FALSE(0.0 < opt);
-}
-
-TEST(OptionalTest, ValueLessEq_Empty) {
- Optional<int> opt;
- EXPECT_TRUE(opt <= 1);
-}
-
-TEST(OptionalTest, ValueLessEq_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_TRUE(opt <= 1);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(opt <= 1);
- }
- {
- Optional<int> opt(2);
- EXPECT_FALSE(opt <= 1);
- }
-}
-
-TEST(OptionalTest, ValueLessEq_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(opt <= 0.0);
-}
-
-TEST(OptionalTest, LessEqValue_Empty) {
- Optional<int> opt;
- EXPECT_FALSE(1 <= opt);
-}
-
-TEST(OptionalTest, LessEqValue_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_FALSE(1 <= opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(1 <= opt);
- }
- {
- Optional<int> opt(2);
- EXPECT_TRUE(1 <= opt);
- }
-}
-
-TEST(OptionalTest, LessEqValue_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(0.0 <= opt);
-}
-
-TEST(OptionalTest, ValueGreater_Empty) {
- Optional<int> opt;
- EXPECT_FALSE(opt > 1);
-}
-
-TEST(OptionalTest, ValueGreater_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_FALSE(opt > 1);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(opt > 1);
- }
- {
- Optional<int> opt(2);
- EXPECT_TRUE(opt > 1);
- }
-}
-
-TEST(OptionalTest, ValueGreater_DifferentType) {
- Optional<int> opt(0);
- EXPECT_FALSE(opt > 0.0);
-}
-
-TEST(OptionalTest, GreaterValue_Empty) {
- Optional<int> opt;
- EXPECT_TRUE(1 > opt);
-}
-
-TEST(OptionalTest, GreaterValue_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_TRUE(1 > opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_FALSE(1 > opt);
- }
- {
- Optional<int> opt(2);
- EXPECT_FALSE(1 > opt);
- }
-}
-
-TEST(OptionalTest, GreaterValue_DifferentType) {
- Optional<int> opt(0);
- EXPECT_FALSE(0.0 > opt);
-}
-
-TEST(OptionalTest, ValueGreaterEq_Empty) {
- Optional<int> opt;
- EXPECT_FALSE(opt >= 1);
-}
-
-TEST(OptionalTest, ValueGreaterEq_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_FALSE(opt >= 1);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(opt >= 1);
- }
- {
- Optional<int> opt(2);
- EXPECT_TRUE(opt >= 1);
- }
-}
-
-TEST(OptionalTest, ValueGreaterEq_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(opt <= 0.0);
-}
-
-TEST(OptionalTest, GreaterEqValue_Empty) {
- Optional<int> opt;
- EXPECT_TRUE(1 >= opt);
-}
-
-TEST(OptionalTest, GreaterEqValue_NotEmpty) {
- {
- Optional<int> opt(0);
- EXPECT_TRUE(1 >= opt);
- }
- {
- Optional<int> opt(1);
- EXPECT_TRUE(1 >= opt);
- }
- {
- Optional<int> opt(2);
- EXPECT_FALSE(1 >= opt);
- }
-}
-
-TEST(OptionalTest, GreaterEqValue_DifferentType) {
- Optional<int> opt(0);
- EXPECT_TRUE(0.0 >= opt);
-}
-
-TEST(OptionalTest, NotEquals) {
- {
- Optional<float> a(0.1f);
- Optional<float> b(0.2f);
- EXPECT_NE(a, b);
- }
-
- {
- Optional<std::string> a("foo");
- Optional<std::string> b("bar");
- EXPECT_NE(a, b);
- }
-
- {
- Optional<int> a(1);
- Optional<double> b(2);
- EXPECT_NE(a, b);
- }
-
- {
- Optional<TestObject> a(TestObject(3, 0.1));
- Optional<TestObject> b(TestObject(4, 1.0));
- EXPECT_TRUE(a != b);
- }
-}
-
-TEST(OptionalTest, NotEqualsNull) {
- {
- Optional<float> a(0.1f);
- Optional<float> b(0.1f);
- b = base::nullopt;
- EXPECT_NE(a, b);
- }
-
- {
- Optional<std::string> a("foo");
- Optional<std::string> b("foo");
- b = base::nullopt;
- EXPECT_NE(a, b);
- }
-
- {
- Optional<TestObject> a(TestObject(3, 0.1));
- Optional<TestObject> b(TestObject(3, 0.1));
- b = base::nullopt;
- EXPECT_TRUE(a != b);
- }
-}
-
-TEST(OptionalTest, MakeOptional) {
- {
- Optional<float> o = make_optional(32.f);
- EXPECT_TRUE(o);
- EXPECT_EQ(32.f, *o);
-
- float value = 3.f;
- o = make_optional(std::move(value));
- EXPECT_TRUE(o);
- EXPECT_EQ(3.f, *o);
- }
-
- {
- Optional<std::string> o = make_optional(std::string("foo"));
- EXPECT_TRUE(o);
- EXPECT_EQ("foo", *o);
-
- std::string value = "bar";
- o = make_optional(std::move(value));
- EXPECT_TRUE(o);
- EXPECT_EQ(std::string("bar"), *o);
- }
-
- {
- Optional<TestObject> o = make_optional(TestObject(3, 0.1));
- EXPECT_TRUE(!!o);
- EXPECT_TRUE(TestObject(3, 0.1) == *o);
-
- TestObject value = TestObject(0, 0.42);
- o = make_optional(std::move(value));
- EXPECT_TRUE(!!o);
- EXPECT_TRUE(TestObject(0, 0.42) == *o);
- EXPECT_EQ(TestObject::State::MOVED_FROM, value.state());
- EXPECT_EQ(TestObject::State::MOVE_ASSIGNED, o->state());
-
- EXPECT_EQ(TestObject::State::MOVE_CONSTRUCTED,
- base::make_optional(std::move(value))->state());
- }
-
- {
- struct Test {
- Test(int a, double b, bool c) : a(a), b(b), c(c) {}
-
- int a;
- double b;
- bool c;
- };
-
- Optional<Test> o = make_optional<Test>(1, 2.0, true);
- EXPECT_TRUE(!!o);
- EXPECT_EQ(1, o->a);
- EXPECT_EQ(2.0, o->b);
- EXPECT_TRUE(o->c);
- }
-
- {
- auto str1 = make_optional<std::string>({'1', '2', '3'});
- EXPECT_EQ("123", *str1);
-
- auto str2 =
- make_optional<std::string>({'a', 'b', 'c'}, std::allocator<char>());
- EXPECT_EQ("abc", *str2);
- }
-}
-
-TEST(OptionalTest, NonMemberSwap_bothNoValue) {
- Optional<TestObject> a, b;
- base::swap(a, b);
-
- EXPECT_FALSE(!!a);
- EXPECT_FALSE(!!b);
- EXPECT_TRUE(TestObject(42, 0.42) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(42, 0.42) == b.value_or(TestObject(42, 0.42)));
-}
-
-TEST(OptionalTest, NonMemberSwap_inHasValue) {
- Optional<TestObject> a(TestObject(1, 0.3));
- Optional<TestObject> b;
- base::swap(a, b);
-
- EXPECT_FALSE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(TestObject(42, 0.42) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(1, 0.3) == b.value_or(TestObject(42, 0.42)));
-}
-
-TEST(OptionalTest, NonMemberSwap_outHasValue) {
- Optional<TestObject> a;
- Optional<TestObject> b(TestObject(1, 0.3));
- base::swap(a, b);
-
- EXPECT_TRUE(!!a);
- EXPECT_FALSE(!!b);
- EXPECT_TRUE(TestObject(1, 0.3) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(42, 0.42) == b.value_or(TestObject(42, 0.42)));
-}
-
-TEST(OptionalTest, NonMemberSwap_bothValue) {
- Optional<TestObject> a(TestObject(0, 0.1));
- Optional<TestObject> b(TestObject(1, 0.3));
- base::swap(a, b);
-
- EXPECT_TRUE(!!a);
- EXPECT_TRUE(!!b);
- EXPECT_TRUE(TestObject(1, 0.3) == a.value_or(TestObject(42, 0.42)));
- EXPECT_TRUE(TestObject(0, 0.1) == b.value_or(TestObject(42, 0.42)));
- EXPECT_EQ(TestObject::State::SWAPPED, a->state());
- EXPECT_EQ(TestObject::State::SWAPPED, b->state());
-}
-
-TEST(OptionalTest, Hash_OptionalReflectsInternal) {
- {
- std::hash<int> int_hash;
- std::hash<Optional<int>> opt_int_hash;
-
- EXPECT_EQ(int_hash(1), opt_int_hash(Optional<int>(1)));
- }
-
- {
- std::hash<std::string> str_hash;
- std::hash<Optional<std::string>> opt_str_hash;
-
- EXPECT_EQ(str_hash(std::string("foobar")),
- opt_str_hash(Optional<std::string>(std::string("foobar"))));
- }
-}
-
-TEST(OptionalTest, Hash_NullOptEqualsNullOpt) {
- std::hash<Optional<int>> opt_int_hash;
- std::hash<Optional<std::string>> opt_str_hash;
-
- EXPECT_EQ(opt_str_hash(Optional<std::string>()),
- opt_int_hash(Optional<int>()));
-}
-
-TEST(OptionalTest, Hash_UseInSet) {
- std::set<Optional<int>> setOptInt;
-
- EXPECT_EQ(setOptInt.end(), setOptInt.find(42));
-
- setOptInt.insert(Optional<int>(3));
- EXPECT_EQ(setOptInt.end(), setOptInt.find(42));
- EXPECT_NE(setOptInt.end(), setOptInt.find(3));
-}
-
-TEST(OptionalTest, HasValue) {
- Optional<int> a;
- EXPECT_FALSE(a.has_value());
-
- a = 42;
- EXPECT_TRUE(a.has_value());
-
- a = nullopt;
- EXPECT_FALSE(a.has_value());
-
- a = 0;
- EXPECT_TRUE(a.has_value());
-
- a = Optional<int>();
- EXPECT_FALSE(a.has_value());
-}
-
-TEST(OptionalTest, Reset_int) {
- Optional<int> a(0);
- EXPECT_TRUE(a.has_value());
- EXPECT_EQ(0, a.value());
-
- a.reset();
- EXPECT_FALSE(a.has_value());
- EXPECT_EQ(-1, a.value_or(-1));
-}
-
-TEST(OptionalTest, Reset_Object) {
- Optional<TestObject> a(TestObject(0, 0.1));
- EXPECT_TRUE(a.has_value());
- EXPECT_EQ(TestObject(0, 0.1), a.value());
-
- a.reset();
- EXPECT_FALSE(a.has_value());
- EXPECT_EQ(TestObject(42, 0.0), a.value_or(TestObject(42, 0.0)));
-}
-
-TEST(OptionalTest, Reset_NoOp) {
- Optional<int> a;
- EXPECT_FALSE(a.has_value());
-
- a.reset();
- EXPECT_FALSE(a.has_value());
-}
-
-TEST(OptionalTest, AssignFromRValue) {
- Optional<TestObject> a;
- EXPECT_FALSE(a.has_value());
-
- TestObject obj;
- a = std::move(obj);
- EXPECT_TRUE(a.has_value());
- EXPECT_EQ(1, a->move_ctors_count());
-}
-
-TEST(OptionalTest, DontCallDefaultCtor) {
- Optional<DeletedDefaultConstructor> a;
- EXPECT_FALSE(a.has_value());
-
- a = base::make_optional<DeletedDefaultConstructor>(42);
- EXPECT_TRUE(a.has_value());
- EXPECT_EQ(42, a->foo());
-}
-
-TEST(OptionalTest, DontCallNewMemberFunction) {
- Optional<DeleteNewOperators> a;
- EXPECT_FALSE(a.has_value());
-
- a = DeleteNewOperators();
- EXPECT_TRUE(a.has_value());
-}
-
-TEST(OptionalTest, Noexcept) {
- // Trivial copy ctor, non-trivial move ctor, nothrow move assign.
- struct Test1 {
- Test1(const Test1&) = default;
- Test1(Test1&&) {}
- Test1& operator=(Test1&&) = default;
- };
- // Non-trivial copy ctor, trivial move ctor, throw move assign.
- struct Test2 {
- Test2(const Test2&) {}
- Test2(Test2&&) = default;
- Test2& operator=(Test2&&) { return *this; }
- };
- // Trivial copy ctor, non-trivial nothrow move ctor.
- struct Test3 {
- Test3(const Test3&) = default;
- Test3(Test3&&) noexcept {}
- };
- // Non-trivial copy ctor, non-trivial nothrow move ctor.
- struct Test4 {
- Test4(const Test4&) {}
- Test4(Test4&&) noexcept {}
- };
- // Non-trivial copy ctor, non-trivial move ctor.
- struct Test5 {
- Test5(const Test5&) {}
- Test5(Test5&&) {}
- };
-
- static_assert(
- noexcept(Optional<int>(std::declval<Optional<int>>())),
- "move constructor for noexcept move-constructible T must be noexcept "
- "(trivial copy, trivial move)");
- static_assert(
- !noexcept(Optional<Test1>(std::declval<Optional<Test1>>())),
- "move constructor for non-noexcept move-constructible T must not be "
- "noexcept (trivial copy)");
- static_assert(
- noexcept(Optional<Test2>(std::declval<Optional<Test2>>())),
- "move constructor for noexcept move-constructible T must be noexcept "
- "(non-trivial copy, trivial move)");
- static_assert(
- noexcept(Optional<Test3>(std::declval<Optional<Test3>>())),
- "move constructor for noexcept move-constructible T must be noexcept "
- "(trivial copy, non-trivial move)");
- static_assert(
- noexcept(Optional<Test4>(std::declval<Optional<Test4>>())),
- "move constructor for noexcept move-constructible T must be noexcept "
- "(non-trivial copy, non-trivial move)");
- static_assert(
- !noexcept(Optional<Test5>(std::declval<Optional<Test5>>())),
- "move constructor for non-noexcept move-constructible T must not be "
- "noexcept (non-trivial copy)");
-
- static_assert(
- noexcept(std::declval<Optional<int>>() = std::declval<Optional<int>>()),
- "move assign for noexcept move-constructible/move-assignable T "
- "must be noexcept");
- static_assert(
- !noexcept(std::declval<Optional<Test1>>() =
- std::declval<Optional<Test1>>()),
- "move assign for non-noexcept move-constructible T must not be noexcept");
- static_assert(
- !noexcept(std::declval<Optional<Test2>>() =
- std::declval<Optional<Test2>>()),
- "move assign for non-noexcept move-assignable T must not be noexcept");
-}
-
-} // namespace base
diff --git a/base/optional_unittest.nc b/base/optional_unittest.nc
deleted file mode 100644
index 62c0196..0000000
--- a/base/optional_unittest.nc
+++ /dev/null
@@ -1,65 +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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include <type_traits>
-
-#include "base/optional.h"
-
-namespace base {
-
-#if defined(NCTEST_EXPLICIT_CONVERTING_COPY_CONSTRUCTOR) // [r"fatal error: no matching function for call to object of type"]
-
-// Optional<T>(const Optional<U>& arg) constructor is marked explicit if
-// T is not convertible from "const U&".
-void WontCompile() {
- struct Test {
- // Declares as explicit so that Test is still constructible from int,
- // but not convertible.
- explicit Test(int a) {}
- };
-
- static_assert(!std::is_convertible<const int&, Test>::value,
- "const int& to Test is convertible");
- const Optional<int> arg(in_place, 1);
- ([](Optional<Test> param) {})(arg);
-}
-
-#elif defined(NCTEST_EXPLICIT_CONVERTING_MOVE_CONSTRUCTOR) // [r"fatal error: no matching function for call to object of type"]
-
-// Optional<T>(Optional<U>&& arg) constructor is marked explicit if
-// T is not convertible from "U&&".
-void WontCompile() {
- struct Test {
- // Declares as explicit so that Test is still constructible from int,
- // but not convertible.
- explicit Test(int a) {}
- };
-
- static_assert(!std::is_convertible<int&&, Test>::value,
- "int&& to Test is convertible");
- ([](Optional<Test> param) {})(Optional<int>(in_place, 1));
-}
-
-#elif defined(NCTEST_EXPLICIT_VALUE_FORWARD_CONSTRUCTOR) // [r"fatal error: no matching function for call to object of type"]
-
-// Optional<T>(U&&) constructor is marked explicit if T is not convertible
-// from U&&.
-void WontCompile() {
- struct Test {
- // Declares as explicit so that Test is still constructible from int,
- // but not convertible.
- explicit Test(int a) {}
- };
-
- static_assert(!std::is_convertible<int&&, Test>::value,
- "int&& to Test is convertible");
- ([](Optional<Test> param) {})(1);
-}
-
-#endif
-
-} // namespace base
diff --git a/base/os_compat_android_unittest.cc b/base/os_compat_android_unittest.cc
deleted file mode 100644
index 7fbdc6d..0000000
--- 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 378064a..0000000
--- 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_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) && !defined(OS_FUCHSIA)
- // 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) && !defined(OS_FUCHSIA)
- 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/pickle_unittest.cc b/base/pickle_unittest.cc
deleted file mode 100644
index 4563047..0000000
--- a/base/pickle_unittest.cc
+++ /dev/null
@@ -1,573 +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/pickle.h"
-
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <memory>
-#include <string>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-const bool testbool1 = false;
-const bool testbool2 = true;
-const int testint = 2'093'847'192;
-const long testlong = 1'093'847'192;
-const uint16_t testuint16 = 32123;
-const uint32_t testuint32 = 1593847192;
-const int64_t testint64 = -0x7E8CA925'3104BDFCLL;
-const uint64_t testuint64 = 0xCE8CA925'3104BDF7ULL;
-const float testfloat = 3.1415926935f;
-const double testdouble = 2.71828182845904523;
-const std::string teststring("Hello world"); // note non-aligned string length
-const std::wstring testwstring(L"Hello, world");
-const string16 teststring16(ASCIIToUTF16("Hello, world"));
-const char testrawstring[] = "Hello new world"; // Test raw string writing
-// Test raw char16 writing, assumes UTF16 encoding is ANSI for alpha chars.
-const char16 testrawstring16[] = {'A', 'l', 'o', 'h', 'a', 0};
-const char testdata[] = "AAA\0BBB\0";
-const int testdatalen = arraysize(testdata) - 1;
-
-// checks that the results can be read correctly from the Pickle
-void VerifyResult(const Pickle& pickle) {
- PickleIterator iter(pickle);
-
- bool outbool;
- EXPECT_TRUE(iter.ReadBool(&outbool));
- EXPECT_FALSE(outbool);
- EXPECT_TRUE(iter.ReadBool(&outbool));
- EXPECT_TRUE(outbool);
-
- int outint;
- EXPECT_TRUE(iter.ReadInt(&outint));
- EXPECT_EQ(testint, outint);
-
- long outlong;
- EXPECT_TRUE(iter.ReadLong(&outlong));
- EXPECT_EQ(testlong, outlong);
-
- uint16_t outuint16;
- EXPECT_TRUE(iter.ReadUInt16(&outuint16));
- EXPECT_EQ(testuint16, outuint16);
-
- uint32_t outuint32;
- EXPECT_TRUE(iter.ReadUInt32(&outuint32));
- EXPECT_EQ(testuint32, outuint32);
-
- int64_t outint64;
- EXPECT_TRUE(iter.ReadInt64(&outint64));
- EXPECT_EQ(testint64, outint64);
-
- uint64_t outuint64;
- EXPECT_TRUE(iter.ReadUInt64(&outuint64));
- EXPECT_EQ(testuint64, outuint64);
-
- float outfloat;
- EXPECT_TRUE(iter.ReadFloat(&outfloat));
- EXPECT_EQ(testfloat, outfloat);
-
- double outdouble;
- EXPECT_TRUE(iter.ReadDouble(&outdouble));
- EXPECT_EQ(testdouble, outdouble);
-
- std::string outstring;
- EXPECT_TRUE(iter.ReadString(&outstring));
- EXPECT_EQ(teststring, outstring);
-
- string16 outstring16;
- EXPECT_TRUE(iter.ReadString16(&outstring16));
- EXPECT_EQ(teststring16, outstring16);
-
- StringPiece outstringpiece;
- EXPECT_TRUE(iter.ReadStringPiece(&outstringpiece));
- EXPECT_EQ(testrawstring, outstringpiece);
-
- StringPiece16 outstringpiece16;
- EXPECT_TRUE(iter.ReadStringPiece16(&outstringpiece16));
- EXPECT_EQ(testrawstring16, outstringpiece16);
-
- const char* outdata;
- int outdatalen;
- EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
- EXPECT_EQ(testdatalen, outdatalen);
- EXPECT_EQ(memcmp(testdata, outdata, outdatalen), 0);
-
- // reads past the end should fail
- EXPECT_FALSE(iter.ReadInt(&outint));
-}
-
-} // namespace
-
-TEST(PickleTest, EncodeDecode) {
- Pickle pickle;
-
- pickle.WriteBool(testbool1);
- pickle.WriteBool(testbool2);
- pickle.WriteInt(testint);
- pickle.WriteLong(testlong);
- pickle.WriteUInt16(testuint16);
- pickle.WriteUInt32(testuint32);
- pickle.WriteInt64(testint64);
- pickle.WriteUInt64(testuint64);
- pickle.WriteFloat(testfloat);
- pickle.WriteDouble(testdouble);
- pickle.WriteString(teststring);
- pickle.WriteString16(teststring16);
- pickle.WriteString(testrawstring);
- pickle.WriteString16(testrawstring16);
- pickle.WriteData(testdata, testdatalen);
- VerifyResult(pickle);
-
- // test copy constructor
- Pickle pickle2(pickle);
- VerifyResult(pickle2);
-
- // test operator=
- Pickle pickle3;
- pickle3 = pickle;
- VerifyResult(pickle3);
-}
-
-// Tests that reading/writing a long works correctly when the source process
-// is 64-bit. We rely on having both 32- and 64-bit trybots to validate both
-// arms of the conditional in this test.
-TEST(PickleTest, LongFrom64Bit) {
- Pickle pickle;
- // Under the hood long is always written as a 64-bit value, so simulate a
- // 64-bit long even on 32-bit architectures by explicitly writing an int64_t.
- pickle.WriteInt64(testint64);
-
- PickleIterator iter(pickle);
- long outlong;
- if (sizeof(long) < sizeof(int64_t)) {
- // ReadLong() should return false when the original written value can't be
- // represented as a long.
-#if GTEST_HAS_DEATH_TEST
- EXPECT_DEATH(ignore_result(iter.ReadLong(&outlong)), "");
-#endif
- } else {
- EXPECT_TRUE(iter.ReadLong(&outlong));
- EXPECT_EQ(testint64, outlong);
- }
-}
-
-// Tests that we can handle really small buffers.
-TEST(PickleTest, SmallBuffer) {
- std::unique_ptr<char[]> buffer(new char[1]);
-
- // We should not touch the buffer.
- Pickle pickle(buffer.get(), 1);
-
- PickleIterator iter(pickle);
- int data;
- EXPECT_FALSE(iter.ReadInt(&data));
-}
-
-// Tests that we can handle improper headers.
-TEST(PickleTest, BigSize) {
- int buffer[] = { 0x56035200, 25, 40, 50 };
-
- Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
-
- PickleIterator iter(pickle);
- int data;
- EXPECT_FALSE(iter.ReadInt(&data));
-}
-
-TEST(PickleTest, UnalignedSize) {
- int buffer[] = { 10, 25, 40, 50 };
-
- Pickle pickle(reinterpret_cast<char*>(buffer), sizeof(buffer));
-
- PickleIterator iter(pickle);
- int data;
- EXPECT_FALSE(iter.ReadInt(&data));
-}
-
-TEST(PickleTest, ZeroLenStr) {
- Pickle pickle;
- pickle.WriteString(std::string());
-
- PickleIterator iter(pickle);
- std::string outstr;
- EXPECT_TRUE(iter.ReadString(&outstr));
- EXPECT_EQ("", outstr);
-}
-
-TEST(PickleTest, ZeroLenStr16) {
- Pickle pickle;
- pickle.WriteString16(string16());
-
- PickleIterator iter(pickle);
- std::string outstr;
- EXPECT_TRUE(iter.ReadString(&outstr));
- EXPECT_EQ("", outstr);
-}
-
-TEST(PickleTest, BadLenStr) {
- Pickle pickle;
- pickle.WriteInt(-2);
-
- PickleIterator iter(pickle);
- std::string outstr;
- EXPECT_FALSE(iter.ReadString(&outstr));
-}
-
-TEST(PickleTest, BadLenStr16) {
- Pickle pickle;
- pickle.WriteInt(-1);
-
- PickleIterator iter(pickle);
- string16 outstr;
- EXPECT_FALSE(iter.ReadString16(&outstr));
-}
-
-TEST(PickleTest, PeekNext) {
- struct CustomHeader : base::Pickle::Header {
- int cookies[10];
- };
-
- Pickle pickle(sizeof(CustomHeader));
-
- pickle.WriteString("Goooooooooooogle");
-
- const char* pickle_data = static_cast<const char*>(pickle.data());
-
- size_t pickle_size;
-
- // Data range doesn't contain header
- EXPECT_FALSE(Pickle::PeekNext(
- sizeof(CustomHeader),
- pickle_data,
- pickle_data + sizeof(CustomHeader) - 1,
- &pickle_size));
-
- // Data range contains header
- EXPECT_TRUE(Pickle::PeekNext(
- sizeof(CustomHeader),
- pickle_data,
- pickle_data + sizeof(CustomHeader),
- &pickle_size));
- EXPECT_EQ(pickle_size, pickle.size());
-
- // Data range contains header and some other data
- EXPECT_TRUE(Pickle::PeekNext(
- sizeof(CustomHeader),
- pickle_data,
- pickle_data + sizeof(CustomHeader) + 1,
- &pickle_size));
- EXPECT_EQ(pickle_size, pickle.size());
-
- // Data range contains full pickle
- EXPECT_TRUE(Pickle::PeekNext(
- sizeof(CustomHeader),
- pickle_data,
- pickle_data + pickle.size(),
- &pickle_size));
- EXPECT_EQ(pickle_size, pickle.size());
-}
-
-TEST(PickleTest, PeekNextOverflow) {
- struct CustomHeader : base::Pickle::Header {
- int cookies[10];
- };
-
- CustomHeader header;
-
- // Check if we can wrap around at all
- if (sizeof(size_t) > sizeof(header.payload_size))
- return;
-
- const char* pickle_data = reinterpret_cast<const char*>(&header);
-
- size_t pickle_size;
-
- // Wrapping around is detected and reported as maximum size_t value
- header.payload_size = static_cast<uint32_t>(
- 1 - static_cast<int32_t>(sizeof(CustomHeader)));
- EXPECT_TRUE(Pickle::PeekNext(
- sizeof(CustomHeader),
- pickle_data,
- pickle_data + sizeof(CustomHeader),
- &pickle_size));
- EXPECT_EQ(pickle_size, std::numeric_limits<size_t>::max());
-
- // Ridiculous pickle sizes are fine (callers are supposed to
- // verify them)
- header.payload_size =
- std::numeric_limits<uint32_t>::max() / 2 - sizeof(CustomHeader);
- EXPECT_TRUE(Pickle::PeekNext(
- sizeof(CustomHeader),
- pickle_data,
- pickle_data + sizeof(CustomHeader),
- &pickle_size));
- EXPECT_EQ(pickle_size, std::numeric_limits<uint32_t>::max() / 2);
-}
-
-TEST(PickleTest, FindNext) {
- Pickle pickle;
- pickle.WriteInt(1);
- pickle.WriteString("Domo");
-
- const char* start = reinterpret_cast<const char*>(pickle.data());
- const char* end = start + pickle.size();
-
- EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end));
- EXPECT_EQ(nullptr, Pickle::FindNext(pickle.header_size_, start, end - 1));
- EXPECT_EQ(end, Pickle::FindNext(pickle.header_size_, start, end + 1));
-}
-
-TEST(PickleTest, FindNextWithIncompleteHeader) {
- size_t header_size = sizeof(Pickle::Header);
- std::unique_ptr<char[]> buffer(new char[header_size - 1]);
- memset(buffer.get(), 0x1, header_size - 1);
-
- const char* start = buffer.get();
- const char* end = start + header_size - 1;
-
- EXPECT_EQ(nullptr, Pickle::FindNext(header_size, start, end));
-}
-
-#if defined(COMPILER_MSVC)
-#pragma warning(push)
-#pragma warning(disable: 4146)
-#endif
-TEST(PickleTest, FindNextOverflow) {
- size_t header_size = sizeof(Pickle::Header);
- size_t header_size2 = 2 * header_size;
- size_t payload_received = 100;
- std::unique_ptr<char[]> buffer(new char[header_size2 + payload_received]);
- const char* start = buffer.get();
- Pickle::Header* header = reinterpret_cast<Pickle::Header*>(buffer.get());
- const char* end = start + header_size2 + payload_received;
- // It is impossible to construct an overflow test otherwise.
- if (sizeof(size_t) > sizeof(header->payload_size) ||
- sizeof(uintptr_t) > sizeof(header->payload_size))
- return;
-
- header->payload_size = -(reinterpret_cast<uintptr_t>(start) + header_size2);
- EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
-
- header->payload_size = -header_size2;
- EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
-
- header->payload_size = 0;
- end = start + header_size;
- EXPECT_EQ(nullptr, Pickle::FindNext(header_size2, start, end));
-}
-#if defined(COMPILER_MSVC)
-#pragma warning(pop)
-#endif
-
-TEST(PickleTest, GetReadPointerAndAdvance) {
- Pickle pickle;
-
- PickleIterator iter(pickle);
- EXPECT_FALSE(iter.GetReadPointerAndAdvance(1));
-
- pickle.WriteInt(1);
- pickle.WriteInt(2);
- int bytes = sizeof(int) * 2;
-
- EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(0));
- EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(1));
- EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(-1));
- EXPECT_TRUE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes));
- EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(bytes + 1));
- EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MAX));
- EXPECT_FALSE(PickleIterator(pickle).GetReadPointerAndAdvance(INT_MIN));
-}
-
-TEST(PickleTest, Resize) {
- size_t unit = Pickle::kPayloadUnit;
- std::unique_ptr<char[]> data(new char[unit]);
- char* data_ptr = data.get();
- for (size_t i = 0; i < unit; i++)
- data_ptr[i] = 'G';
-
- // construct a message that will be exactly the size of one payload unit,
- // note that any data will have a 4-byte header indicating the size
- const size_t payload_size_after_header = unit - sizeof(uint32_t);
- Pickle pickle;
- pickle.WriteData(
- data_ptr, static_cast<int>(payload_size_after_header - sizeof(uint32_t)));
- size_t cur_payload = payload_size_after_header;
-
- // note: we assume 'unit' is a power of 2
- EXPECT_EQ(unit, pickle.capacity_after_header());
- EXPECT_EQ(pickle.payload_size(), payload_size_after_header);
-
- // fill out a full page (noting data header)
- pickle.WriteData(data_ptr, static_cast<int>(unit - sizeof(uint32_t)));
- cur_payload += unit;
- EXPECT_EQ(unit * 2, pickle.capacity_after_header());
- EXPECT_EQ(cur_payload, pickle.payload_size());
-
- // one more byte should double the capacity
- pickle.WriteData(data_ptr, 1);
- cur_payload += 8;
- EXPECT_EQ(unit * 4, pickle.capacity_after_header());
- EXPECT_EQ(cur_payload, pickle.payload_size());
-}
-
-namespace {
-
-struct CustomHeader : Pickle::Header {
- int blah;
-};
-
-} // namespace
-
-TEST(PickleTest, HeaderPadding) {
- const uint32_t kMagic = 0x12345678;
-
- Pickle pickle(sizeof(CustomHeader));
- pickle.WriteInt(kMagic);
-
- // this should not overwrite the 'int' payload
- pickle.headerT<CustomHeader>()->blah = 10;
-
- PickleIterator iter(pickle);
- int result;
- ASSERT_TRUE(iter.ReadInt(&result));
-
- EXPECT_EQ(static_cast<uint32_t>(result), kMagic);
-}
-
-TEST(PickleTest, EqualsOperator) {
- Pickle source;
- source.WriteInt(1);
-
- Pickle copy_refs_source_buffer(static_cast<const char*>(source.data()),
- source.size());
- Pickle copy;
- copy = copy_refs_source_buffer;
- ASSERT_EQ(source.size(), copy.size());
-}
-
-TEST(PickleTest, EvilLengths) {
- Pickle source;
- std::string str(100000, 'A');
- source.WriteData(str.c_str(), 100000);
- // ReadString16 used to have its read buffer length calculation wrong leading
- // to out-of-bounds reading.
- PickleIterator iter(source);
- string16 str16;
- EXPECT_FALSE(iter.ReadString16(&str16));
-
- // And check we didn't break ReadString16.
- str16 = (wchar_t) 'A';
- Pickle str16_pickle;
- str16_pickle.WriteString16(str16);
- iter = PickleIterator(str16_pickle);
- EXPECT_TRUE(iter.ReadString16(&str16));
- EXPECT_EQ(1U, str16.length());
-
- // Check we don't fail in a length check with invalid String16 size.
- // (1<<31) * sizeof(char16) == 0, so this is particularly evil.
- Pickle bad_len;
- bad_len.WriteInt(1 << 31);
- iter = PickleIterator(bad_len);
- EXPECT_FALSE(iter.ReadString16(&str16));
-}
-
-// Check we can write zero bytes of data and 'data' can be NULL.
-TEST(PickleTest, ZeroLength) {
- Pickle pickle;
- pickle.WriteData(nullptr, 0);
-
- PickleIterator iter(pickle);
- const char* outdata;
- int outdatalen;
- EXPECT_TRUE(iter.ReadData(&outdata, &outdatalen));
- EXPECT_EQ(0, outdatalen);
- // We can't assert that outdata is NULL.
-}
-
-// Check that ReadBytes works properly with an iterator initialized to NULL.
-TEST(PickleTest, ReadBytes) {
- Pickle pickle;
- int data = 0x7abcd;
- pickle.WriteBytes(&data, sizeof(data));
-
- PickleIterator iter(pickle);
- const char* outdata_char = nullptr;
- EXPECT_TRUE(iter.ReadBytes(&outdata_char, sizeof(data)));
-
- int outdata;
- memcpy(&outdata, outdata_char, sizeof(outdata));
- EXPECT_EQ(data, outdata);
-}
-
-// Checks that when a pickle is deep-copied, the result is not larger than
-// needed.
-TEST(PickleTest, DeepCopyResize) {
- Pickle pickle;
- while (pickle.capacity_after_header() != pickle.payload_size())
- pickle.WriteBool(true);
-
- // Make a deep copy.
- Pickle pickle2(pickle);
-
- // Check that there isn't any extraneous capacity.
- EXPECT_EQ(pickle.capacity_after_header(), pickle2.capacity_after_header());
-}
-
-namespace {
-
-// Publicly exposes the ClaimBytes interface for testing.
-class TestingPickle : public Pickle {
- public:
- TestingPickle() = default;
-
- void* ClaimBytes(size_t num_bytes) { return Pickle::ClaimBytes(num_bytes); }
-};
-
-} // namespace
-
-// Checks that claimed bytes are zero-initialized.
-TEST(PickleTest, ClaimBytesInitialization) {
- static const int kChunkSize = 64;
- TestingPickle pickle;
- const char* bytes = static_cast<const char*>(pickle.ClaimBytes(kChunkSize));
- for (size_t i = 0; i < kChunkSize; ++i) {
- EXPECT_EQ(0, bytes[i]);
- }
-}
-
-// Checks that ClaimBytes properly advances the write offset.
-TEST(PickleTest, ClaimBytes) {
- std::string data("Hello, world!");
-
- TestingPickle pickle;
- pickle.WriteUInt32(data.size());
- void* bytes = pickle.ClaimBytes(data.size());
- pickle.WriteInt(42);
- memcpy(bytes, data.data(), data.size());
-
- PickleIterator iter(pickle);
- uint32_t out_data_length;
- EXPECT_TRUE(iter.ReadUInt32(&out_data_length));
- EXPECT_EQ(data.size(), out_data_length);
-
- const char* out_data = nullptr;
- EXPECT_TRUE(iter.ReadBytes(&out_data, out_data_length));
- EXPECT_EQ(data, std::string(out_data, out_data_length));
-
- int out_value;
- EXPECT_TRUE(iter.ReadInt(&out_value));
- EXPECT_EQ(42, out_value);
-}
-
-} // namespace base
diff --git a/base/posix/file_descriptor_shuffle_unittest.cc b/base/posix/file_descriptor_shuffle_unittest.cc
deleted file mode 100644
index 3dfbf7e..0000000
--- a/base/posix/file_descriptor_shuffle_unittest.cc
+++ /dev/null
@@ -1,281 +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/posix/file_descriptor_shuffle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// 'Duplicated' file descriptors start at this number
-const int kDuplicateBase = 1000;
-
-} // namespace
-
-namespace base {
-
-struct Action {
- enum Type {
- CLOSE,
- MOVE,
- DUPLICATE,
- };
-
- Action(Type in_type, int in_fd1, int in_fd2 = -1)
- : type(in_type),
- fd1(in_fd1),
- fd2(in_fd2) {
- }
-
- bool operator==(const Action& other) const {
- return other.type == type &&
- other.fd1 == fd1 &&
- other.fd2 == fd2;
- }
-
- Type type;
- int fd1;
- int fd2;
-};
-
-class InjectionTracer : public InjectionDelegate {
- public:
- InjectionTracer()
- : next_duplicate_(kDuplicateBase) {
- }
-
- bool Duplicate(int* result, int fd) override {
- *result = next_duplicate_++;
- actions_.push_back(Action(Action::DUPLICATE, *result, fd));
- return true;
- }
-
- bool Move(int src, int dest) override {
- actions_.push_back(Action(Action::MOVE, src, dest));
- return true;
- }
-
- void Close(int fd) override { actions_.push_back(Action(Action::CLOSE, fd)); }
-
- const std::vector<Action>& actions() const { return actions_; }
-
- private:
- int next_duplicate_;
- std::vector<Action> actions_;
-};
-
-TEST(FileDescriptorShuffleTest, Empty) {
- InjectiveMultimap map;
- InjectionTracer tracer;
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- EXPECT_EQ(0u, tracer.actions().size());
-}
-
-TEST(FileDescriptorShuffleTest, Noop) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 0, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- EXPECT_EQ(0u, tracer.actions().size());
-}
-
-TEST(FileDescriptorShuffleTest, NoopAndClose) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 0, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- EXPECT_EQ(0u, tracer.actions().size());
-}
-
-TEST(FileDescriptorShuffleTest, Simple1) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(1u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
-}
-
-TEST(FileDescriptorShuffleTest, Simple2) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, false));
- map.push_back(InjectionArc(2, 3, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(2u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 2, 3));
-}
-
-TEST(FileDescriptorShuffleTest, Simple3) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(2u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::CLOSE, 0));
-}
-
-TEST(FileDescriptorShuffleTest, Simple4) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(10, 0, true));
- map.push_back(InjectionArc(1, 1, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(2u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 10, 0));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::CLOSE, 10));
-}
-
-TEST(FileDescriptorShuffleTest, Cycle) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, false));
- map.push_back(InjectionArc(1, 0, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(4u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] ==
- Action(Action::DUPLICATE, kDuplicateBase, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
- EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
-}
-
-TEST(FileDescriptorShuffleTest, CycleAndClose1) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, true));
- map.push_back(InjectionArc(1, 0, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(4u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] ==
- Action(Action::DUPLICATE, kDuplicateBase, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
- EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
-}
-
-TEST(FileDescriptorShuffleTest, CycleAndClose2) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, false));
- map.push_back(InjectionArc(1, 0, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(4u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] ==
- Action(Action::DUPLICATE, kDuplicateBase, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
- EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
-}
-
-TEST(FileDescriptorShuffleTest, CycleAndClose3) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, true));
- map.push_back(InjectionArc(1, 0, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(4u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] ==
- Action(Action::DUPLICATE, kDuplicateBase, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
- EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
-}
-
-TEST(FileDescriptorShuffleTest, Fanout) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, false));
- map.push_back(InjectionArc(0, 2, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(2u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
-}
-
-TEST(FileDescriptorShuffleTest, FanoutAndClose1) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, true));
- map.push_back(InjectionArc(0, 2, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(3u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
-}
-
-TEST(FileDescriptorShuffleTest, FanoutAndClose2) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, false));
- map.push_back(InjectionArc(0, 2, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(3u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
-}
-
-TEST(FileDescriptorShuffleTest, FanoutAndClose3) {
- InjectiveMultimap map;
- InjectionTracer tracer;
- map.push_back(InjectionArc(0, 1, true));
- map.push_back(InjectionArc(0, 2, true));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
- ASSERT_EQ(3u, tracer.actions().size());
- EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
- EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
- EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
-}
-
-class FailingDelegate : public InjectionDelegate {
- public:
- bool Duplicate(int* result, int fd) override { return false; }
-
- bool Move(int src, int dest) override { return false; }
-
- void Close(int fd) override {}
-};
-
-TEST(FileDescriptorShuffleTest, EmptyWithFailure) {
- InjectiveMultimap map;
- FailingDelegate failing;
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
-}
-
-TEST(FileDescriptorShuffleTest, NoopWithFailure) {
- InjectiveMultimap map;
- FailingDelegate failing;
- map.push_back(InjectionArc(0, 0, false));
-
- EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
-}
-
-TEST(FileDescriptorShuffleTest, Simple1WithFailure) {
- InjectiveMultimap map;
- FailingDelegate failing;
- map.push_back(InjectionArc(0, 1, false));
-
- EXPECT_FALSE(PerformInjectiveMultimap(map, &failing));
-}
-
-} // namespace base
diff --git a/base/posix/unix_domain_socket_unittest.cc b/base/posix/unix_domain_socket_unittest.cc
deleted file mode 100644
index f626de5..0000000
--- a/base/posix/unix_domain_socket_unittest.cc
+++ /dev/null
@@ -1,183 +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 "build_config.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_file.h"
-#include "base/location.h"
-#include "base/pickle.h"
-#include "base/posix/unix_domain_socket.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Callers should use ASSERT_NO_FATAL_FAILURE with this function, to
-// ensure that execution is aborted if the function has assertion failure.
-void CreateSocketPair(int fds[2]) {
-#if defined(OS_MACOSX)
- // Mac OS does not support SOCK_SEQPACKET.
- int flags = SOCK_STREAM;
-#else
- int flags = SOCK_SEQPACKET;
-#endif
- ASSERT_EQ(0, socketpair(AF_UNIX, flags, 0, fds));
-#if defined(OS_MACOSX)
- // On OSX an attempt to read or write to a closed socket may generate a
- // SIGPIPE rather than returning -1, corrected with SO_NOSIGPIPE option.
- int nosigpipe = 1;
- ASSERT_EQ(0, setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe,
- sizeof(nosigpipe)));
- ASSERT_EQ(0, setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &nosigpipe,
- sizeof(nosigpipe)));
-#endif
-}
-
-TEST(UnixDomainSocketTest, SendRecvMsgAbortOnReplyFDClose) {
- Thread message_thread("UnixDomainSocketTest");
- ASSERT_TRUE(message_thread.Start());
- int fds[2];
- ASSERT_NO_FATAL_FAILURE(CreateSocketPair(fds));
- ScopedFD scoped_fd0(fds[0]);
- ScopedFD scoped_fd1(fds[1]);
-
- // Have the thread send a synchronous message via the socket.
- Pickle request;
- message_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(IgnoreResult(&UnixDomainSocket::SendRecvMsg), fds[1],
- nullptr, 0U, nullptr, request));
-
- // Receive the message.
- std::vector<ScopedFD> message_fds;
- uint8_t buffer[16];
- ASSERT_EQ(
- static_cast<int>(request.size()),
- UnixDomainSocket::RecvMsg(fds[0], buffer, sizeof(buffer), &message_fds));
- ASSERT_EQ(1U, message_fds.size());
-
- // Close the reply FD.
- message_fds.clear();
-
- // Check that the thread didn't get blocked.
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- message_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&event)));
- ASSERT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(5000)));
-}
-
-TEST(UnixDomainSocketTest, SendRecvMsgAvoidsSIGPIPE) {
- // Make sure SIGPIPE isn't being ignored.
- struct sigaction act = {}, oldact;
- act.sa_handler = SIG_DFL;
- ASSERT_EQ(0, sigaction(SIGPIPE, &act, &oldact));
- int fds[2];
- ASSERT_NO_FATAL_FAILURE(CreateSocketPair(fds));
- ScopedFD scoped_fd1(fds[1]);
- ASSERT_EQ(0, IGNORE_EINTR(close(fds[0])));
-
- // Have the thread send a synchronous message via the socket. Unless the
- // message is sent with MSG_NOSIGNAL, this shall result in SIGPIPE.
- Pickle request;
- ASSERT_EQ(
- -1, UnixDomainSocket::SendRecvMsg(fds[1], nullptr, 0U, nullptr, request));
- ASSERT_EQ(EPIPE, errno);
- // Restore the SIGPIPE handler.
- ASSERT_EQ(0, sigaction(SIGPIPE, &oldact, nullptr));
-}
-
-// Simple sanity check within a single process that receiving PIDs works.
-TEST(UnixDomainSocketTest, RecvPid) {
- int fds[2];
- ASSERT_NO_FATAL_FAILURE(CreateSocketPair(fds));
- ScopedFD recv_sock(fds[0]);
- ScopedFD send_sock(fds[1]);
-
- ASSERT_TRUE(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
-
- static const char kHello[] = "hello";
- ASSERT_TRUE(UnixDomainSocket::SendMsg(send_sock.get(), kHello, sizeof(kHello),
- std::vector<int>()));
-
- // Extra receiving buffer space to make sure we really received only
- // sizeof(kHello) bytes and it wasn't just truncated to fit the buffer.
- char buf[sizeof(kHello) + 1];
- ProcessId sender_pid;
- std::vector<ScopedFD> fd_vec;
- const ssize_t nread = UnixDomainSocket::RecvMsgWithPid(
- recv_sock.get(), buf, sizeof(buf), &fd_vec, &sender_pid);
- ASSERT_EQ(sizeof(kHello), static_cast<size_t>(nread));
- ASSERT_EQ(0, memcmp(buf, kHello, sizeof(kHello)));
- ASSERT_EQ(0U, fd_vec.size());
-
- ASSERT_EQ(getpid(), sender_pid);
-}
-
-// Same as above, but send the max number of file descriptors too.
-TEST(UnixDomainSocketTest, RecvPidWithMaxDescriptors) {
- int fds[2];
- ASSERT_NO_FATAL_FAILURE(CreateSocketPair(fds));
- ScopedFD recv_sock(fds[0]);
- ScopedFD send_sock(fds[1]);
-
- ASSERT_TRUE(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
-
- static const char kHello[] = "hello";
- std::vector<int> send_fds(UnixDomainSocket::kMaxFileDescriptors,
- send_sock.get());
- ASSERT_TRUE(UnixDomainSocket::SendMsg(send_sock.get(), kHello, sizeof(kHello),
- send_fds));
-
- // Extra receiving buffer space to make sure we really received only
- // sizeof(kHello) bytes and it wasn't just truncated to fit the buffer.
- char buf[sizeof(kHello) + 1];
- ProcessId sender_pid;
- std::vector<ScopedFD> recv_fds;
- const ssize_t nread = UnixDomainSocket::RecvMsgWithPid(
- recv_sock.get(), buf, sizeof(buf), &recv_fds, &sender_pid);
- ASSERT_EQ(sizeof(kHello), static_cast<size_t>(nread));
- ASSERT_EQ(0, memcmp(buf, kHello, sizeof(kHello)));
- ASSERT_EQ(UnixDomainSocket::kMaxFileDescriptors, recv_fds.size());
-
- ASSERT_EQ(getpid(), sender_pid);
-}
-
-// Check that RecvMsgWithPid doesn't DCHECK fail when reading EOF from a
-// disconnected socket.
-TEST(UnixDomianSocketTest, RecvPidDisconnectedSocket) {
- int fds[2];
- ASSERT_NO_FATAL_FAILURE(CreateSocketPair(fds));
- ScopedFD recv_sock(fds[0]);
- ScopedFD send_sock(fds[1]);
-
- ASSERT_TRUE(UnixDomainSocket::EnableReceiveProcessId(recv_sock.get()));
-
- send_sock.reset();
-
- char ch;
- ProcessId sender_pid;
- std::vector<ScopedFD> recv_fds;
- const ssize_t nread = UnixDomainSocket::RecvMsgWithPid(
- recv_sock.get(), &ch, sizeof(ch), &recv_fds, &sender_pid);
- ASSERT_EQ(0, nread);
- ASSERT_EQ(-1, sender_pid);
- ASSERT_EQ(0U, recv_fds.size());
-}
-
-} // namespace
-
-} // 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 7f2a84b..0000000
--- 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 3a565ee..0000000
--- a/base/process/memory_unittest.cc
+++ /dev/null
@@ -1,91 +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/compiler_specific.h"
-#include "base/debug/alias.h"
-#include "base/memory/aligned_memory.h"
-#include "base/strings/stringprintf.h"
-#include "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) {
- // 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
-}
-
-#endif // defined(OS_MACOSX)
-
-TEST(MemoryTest, AllocatorShimWorking) {
-#if defined(OS_MACOSX)
- base::allocator::InterceptAllocationsMac();
-#endif
- ASSERT_TRUE(base::allocator::IsAllocatorInitialized());
-
-#if defined(OS_MACOSX)
- base::allocator::UninterceptMallocZonesForTesting();
-#endif
-}
diff --git a/base/process/process_info_unittest.cc b/base/process/process_info_unittest.cc
deleted file mode 100644
index 51b15b9..0000000
--- a/base/process/process_info_unittest.cc
+++ /dev/null
@@ -1,22 +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/process/process_info.h"
-
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// See https://crbug.com/726484 for Fuchsia.
-// Cannot read boot time on Android O, crbug.com/788870.
-#if !defined(OS_IOS) && !defined(OS_FUCHSIA) && !defined(OS_ANDROID)
-TEST(ProcessInfoTest, CreationTime) {
- Time creation_time = CurrentProcessInfo::CreationTime();
- ASSERT_FALSE(creation_time.is_null());
-}
-#endif // !defined(OS_IOS) && !defined(OS_FUCHSIA) && !defined(OS_ANDROID)
-
-} // namespace base
diff --git a/base/process/process_metrics_unittest.cc b/base/process/process_metrics_unittest.cc
deleted file mode 100644
index aec7be1..0000000
--- a/base/process/process_metrics_unittest.cc
+++ /dev/null
@@ -1,633 +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/process/process_metrics.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <sstream>
-#include <string>
-#include <vector>
-
-#include "base/bind.h"
-#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/memory/shared_memory.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/sys_info.h"
-#include "base/test/multiprocess_test.h"
-#include "base/threading/thread.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-#if defined(OS_MACOSX)
-#include <sys/mman.h>
-#endif
-
-namespace base {
-namespace debug {
-
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
-namespace {
-
-void BusyWork(std::vector<std::string>* vec) {
- int64_t test_value = 0;
- for (int i = 0; i < 100000; ++i) {
- ++test_value;
- vec->push_back(Int64ToString(test_value));
- }
-}
-
-} // namespace
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
-
-// Tests for SystemMetrics.
-// Exists as a class so it can be a friend of SystemMetrics.
-class SystemMetricsTest : public testing::Test {
- public:
- SystemMetricsTest() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SystemMetricsTest);
-};
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-TEST_F(SystemMetricsTest, IsValidDiskName) {
- const char invalid_input1[] = "";
- const char invalid_input2[] = "s";
- const char invalid_input3[] = "sdz+";
- const char invalid_input4[] = "hda0";
- const char invalid_input5[] = "mmcbl";
- const char invalid_input6[] = "mmcblka";
- const char invalid_input7[] = "mmcblkb";
- const char invalid_input8[] = "mmmblk0";
-
- EXPECT_FALSE(IsValidDiskName(invalid_input1));
- EXPECT_FALSE(IsValidDiskName(invalid_input2));
- EXPECT_FALSE(IsValidDiskName(invalid_input3));
- EXPECT_FALSE(IsValidDiskName(invalid_input4));
- EXPECT_FALSE(IsValidDiskName(invalid_input5));
- EXPECT_FALSE(IsValidDiskName(invalid_input6));
- EXPECT_FALSE(IsValidDiskName(invalid_input7));
- EXPECT_FALSE(IsValidDiskName(invalid_input8));
-
- const char valid_input1[] = "sda";
- const char valid_input2[] = "sdaaaa";
- const char valid_input3[] = "hdz";
- const char valid_input4[] = "mmcblk0";
- const char valid_input5[] = "mmcblk999";
-
- EXPECT_TRUE(IsValidDiskName(valid_input1));
- EXPECT_TRUE(IsValidDiskName(valid_input2));
- EXPECT_TRUE(IsValidDiskName(valid_input3));
- EXPECT_TRUE(IsValidDiskName(valid_input4));
- EXPECT_TRUE(IsValidDiskName(valid_input5));
-}
-
-TEST_F(SystemMetricsTest, ParseMeminfo) {
- SystemMemoryInfoKB meminfo;
- const char invalid_input1[] = "abc";
- const char invalid_input2[] = "MemTotal:";
- // Partial file with no MemTotal
- const char invalid_input3[] =
- "MemFree: 3913968 kB\n"
- "Buffers: 2348340 kB\n"
- "Cached: 49071596 kB\n"
- "SwapCached: 12 kB\n"
- "Active: 36393900 kB\n"
- "Inactive: 21221496 kB\n"
- "Active(anon): 5674352 kB\n"
- "Inactive(anon): 633992 kB\n";
- EXPECT_FALSE(ParseProcMeminfo(invalid_input1, &meminfo));
- EXPECT_FALSE(ParseProcMeminfo(invalid_input2, &meminfo));
- EXPECT_FALSE(ParseProcMeminfo(invalid_input3, &meminfo));
-
- const char valid_input1[] =
- "MemTotal: 3981504 kB\n"
- "MemFree: 140764 kB\n"
- "MemAvailable: 535413 kB\n"
- "Buffers: 116480 kB\n"
- "Cached: 406160 kB\n"
- "SwapCached: 21304 kB\n"
- "Active: 3152040 kB\n"
- "Inactive: 472856 kB\n"
- "Active(anon): 2972352 kB\n"
- "Inactive(anon): 270108 kB\n"
- "Active(file): 179688 kB\n"
- "Inactive(file): 202748 kB\n"
- "Unevictable: 0 kB\n"
- "Mlocked: 0 kB\n"
- "SwapTotal: 5832280 kB\n"
- "SwapFree: 3672368 kB\n"
- "Dirty: 184 kB\n"
- "Writeback: 0 kB\n"
- "AnonPages: 3101224 kB\n"
- "Mapped: 142296 kB\n"
- "Shmem: 140204 kB\n"
- "Slab: 54212 kB\n"
- "SReclaimable: 30936 kB\n"
- "SUnreclaim: 23276 kB\n"
- "KernelStack: 2464 kB\n"
- "PageTables: 24812 kB\n"
- "NFS_Unstable: 0 kB\n"
- "Bounce: 0 kB\n"
- "WritebackTmp: 0 kB\n"
- "CommitLimit: 7823032 kB\n"
- "Committed_AS: 7973536 kB\n"
- "VmallocTotal: 34359738367 kB\n"
- "VmallocUsed: 375940 kB\n"
- "VmallocChunk: 34359361127 kB\n"
- "DirectMap4k: 72448 kB\n"
- "DirectMap2M: 4061184 kB\n";
- // output from a much older kernel where the Active and Inactive aren't
- // broken down into anon and file and Huge Pages are enabled
- const char valid_input2[] =
- "MemTotal: 255908 kB\n"
- "MemFree: 69936 kB\n"
- "Buffers: 15812 kB\n"
- "Cached: 115124 kB\n"
- "SwapCached: 0 kB\n"
- "Active: 92700 kB\n"
- "Inactive: 63792 kB\n"
- "HighTotal: 0 kB\n"
- "HighFree: 0 kB\n"
- "LowTotal: 255908 kB\n"
- "LowFree: 69936 kB\n"
- "SwapTotal: 524280 kB\n"
- "SwapFree: 524200 kB\n"
- "Dirty: 4 kB\n"
- "Writeback: 0 kB\n"
- "Mapped: 42236 kB\n"
- "Slab: 25912 kB\n"
- "Committed_AS: 118680 kB\n"
- "PageTables: 1236 kB\n"
- "VmallocTotal: 3874808 kB\n"
- "VmallocUsed: 1416 kB\n"
- "VmallocChunk: 3872908 kB\n"
- "HugePages_Total: 0\n"
- "HugePages_Free: 0\n"
- "Hugepagesize: 4096 kB\n";
-
- EXPECT_TRUE(ParseProcMeminfo(valid_input1, &meminfo));
- EXPECT_EQ(meminfo.total, 3981504);
- EXPECT_EQ(meminfo.free, 140764);
- EXPECT_EQ(meminfo.available, 535413);
- EXPECT_EQ(meminfo.buffers, 116480);
- EXPECT_EQ(meminfo.cached, 406160);
- EXPECT_EQ(meminfo.active_anon, 2972352);
- EXPECT_EQ(meminfo.active_file, 179688);
- EXPECT_EQ(meminfo.inactive_anon, 270108);
- EXPECT_EQ(meminfo.inactive_file, 202748);
- EXPECT_EQ(meminfo.swap_total, 5832280);
- EXPECT_EQ(meminfo.swap_free, 3672368);
- EXPECT_EQ(meminfo.dirty, 184);
- EXPECT_EQ(meminfo.reclaimable, 30936);
-#if defined(OS_CHROMEOS)
- EXPECT_EQ(meminfo.shmem, 140204);
- EXPECT_EQ(meminfo.slab, 54212);
-#endif
- EXPECT_EQ(355725,
- base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024);
- // Simulate as if there is no MemAvailable.
- meminfo.available = 0;
- EXPECT_EQ(374448,
- base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024);
- meminfo = {};
- EXPECT_TRUE(ParseProcMeminfo(valid_input2, &meminfo));
- EXPECT_EQ(meminfo.total, 255908);
- EXPECT_EQ(meminfo.free, 69936);
- EXPECT_EQ(meminfo.available, 0);
- EXPECT_EQ(meminfo.buffers, 15812);
- EXPECT_EQ(meminfo.cached, 115124);
- EXPECT_EQ(meminfo.swap_total, 524280);
- EXPECT_EQ(meminfo.swap_free, 524200);
- EXPECT_EQ(meminfo.dirty, 4);
- EXPECT_EQ(69936,
- base::SysInfo::AmountOfAvailablePhysicalMemory(meminfo) / 1024);
-}
-
-TEST_F(SystemMetricsTest, ParseVmstat) {
- VmStatInfo vmstat;
- // part of vmstat from a 3.2 kernel with numa enabled
- const char valid_input1[] =
- "nr_free_pages 905104\n"
- "nr_inactive_anon 142478"
- "nr_active_anon 1520046\n"
- "nr_inactive_file 4481001\n"
- "nr_active_file 8313439\n"
- "nr_unevictable 5044\n"
- "nr_mlock 5044\n"
- "nr_anon_pages 1633780\n"
- "nr_mapped 104742\n"
- "nr_file_pages 12828218\n"
- "nr_dirty 245\n"
- "nr_writeback 0\n"
- "nr_slab_reclaimable 831609\n"
- "nr_slab_unreclaimable 41164\n"
- "nr_page_table_pages 31470\n"
- "nr_kernel_stack 1735\n"
- "nr_unstable 0\n"
- "nr_bounce 0\n"
- "nr_vmscan_write 406\n"
- "nr_vmscan_immediate_reclaim 281\n"
- "nr_writeback_temp 0\n"
- "nr_isolated_anon 0\n"
- "nr_isolated_file 0\n"
- "nr_shmem 28820\n"
- "nr_dirtied 84674644\n"
- "nr_written 75307109\n"
- "nr_anon_transparent_hugepages 0\n"
- "nr_dirty_threshold 1536206\n"
- "nr_dirty_background_threshold 768103\n"
- "pgpgin 30777108\n"
- "pgpgout 319023278\n"
- "pswpin 179\n"
- "pswpout 406\n"
- "pgalloc_dma 0\n"
- "pgalloc_dma32 20833399\n"
- "pgalloc_normal 1622609290\n"
- "pgalloc_movable 0\n"
- "pgfree 1644355583\n"
- "pgactivate 75391882\n"
- "pgdeactivate 4121019\n"
- "pgfault 2542879679\n"
- "pgmajfault 487192\n";
- const char valid_input2[] =
- "nr_free_pages 180125\n"
- "nr_inactive_anon 51\n"
- "nr_active_anon 38832\n"
- "nr_inactive_file 50171\n"
- "nr_active_file 47510\n"
- "nr_unevictable 0\n"
- "nr_mlock 0\n"
- "nr_anon_pages 38825\n"
- "nr_mapped 24043\n"
- "nr_file_pages 97733\n"
- "nr_dirty 0\n"
- "nr_writeback 0\n"
- "nr_slab_reclaimable 4032\n"
- "nr_slab_unreclaimable 2848\n"
- "nr_page_table_pages 1505\n"
- "nr_kernel_stack 626\n"
- "nr_unstable 0\n"
- "nr_bounce 0\n"
- "nr_vmscan_write 0\n"
- "nr_vmscan_immediate_reclaim 0\n"
- "nr_writeback_temp 0\n"
- "nr_isolated_anon 0\n"
- "nr_isolated_file 0\n"
- "nr_shmem 58\n"
- "nr_dirtied 435358\n"
- "nr_written 401258\n"
- "nr_anon_transparent_hugepages 0\n"
- "nr_dirty_threshold 18566\n"
- "nr_dirty_background_threshold 4641\n"
- "pgpgin 299464\n"
- "pgpgout 2437788\n"
- "pswpin 12\n"
- "pswpout 901\n"
- "pgalloc_normal 144213030\n"
- "pgalloc_high 164501274\n"
- "pgalloc_movable 0\n"
- "pgfree 308894908\n"
- "pgactivate 239320\n"
- "pgdeactivate 1\n"
- "pgfault 716044601\n"
- "pgmajfault 2023\n"
- "pgrefill_normal 0\n"
- "pgrefill_high 0\n"
- "pgrefill_movable 0\n";
- EXPECT_TRUE(ParseProcVmstat(valid_input1, &vmstat));
- EXPECT_EQ(179LU, vmstat.pswpin);
- EXPECT_EQ(406LU, vmstat.pswpout);
- EXPECT_EQ(487192LU, vmstat.pgmajfault);
- EXPECT_TRUE(ParseProcVmstat(valid_input2, &vmstat));
- EXPECT_EQ(12LU, vmstat.pswpin);
- EXPECT_EQ(901LU, vmstat.pswpout);
- EXPECT_EQ(2023LU, vmstat.pgmajfault);
-
- const char missing_pgmajfault_input[] =
- "pswpin 12\n"
- "pswpout 901\n";
- EXPECT_FALSE(ParseProcVmstat(missing_pgmajfault_input, &vmstat));
- const char empty_input[] = "";
- EXPECT_FALSE(ParseProcVmstat(empty_input, &vmstat));
-}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
-#if defined(OS_LINUX) || defined(OS_CHROMEOS) || defined(OS_WIN)
-
-// Test that ProcessMetrics::GetPlatformIndependentCPUUsage() doesn't return
-// negative values when the number of threads running on the process decreases
-// between two successive calls to it.
-TEST_F(SystemMetricsTest, TestNoNegativeCpuUsage) {
- ProcessHandle handle = GetCurrentProcessHandle();
- std::unique_ptr<ProcessMetrics> metrics(
- ProcessMetrics::CreateProcessMetrics(handle));
-
- EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
- Thread thread1("thread1");
- Thread thread2("thread2");
- Thread thread3("thread3");
-
- thread1.StartAndWaitForTesting();
- thread2.StartAndWaitForTesting();
- thread3.StartAndWaitForTesting();
-
- ASSERT_TRUE(thread1.IsRunning());
- ASSERT_TRUE(thread2.IsRunning());
- ASSERT_TRUE(thread3.IsRunning());
-
- std::vector<std::string> vec1;
- std::vector<std::string> vec2;
- std::vector<std::string> vec3;
-
- thread1.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec1));
- thread2.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec2));
- thread3.task_runner()->PostTask(FROM_HERE, BindOnce(&BusyWork, &vec3));
-
- TimeDelta prev_cpu_usage = metrics->GetCumulativeCPUUsage();
- EXPECT_GE(prev_cpu_usage, TimeDelta());
- EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
-
- thread1.Stop();
- TimeDelta current_cpu_usage = metrics->GetCumulativeCPUUsage();
- EXPECT_GE(current_cpu_usage, prev_cpu_usage);
- prev_cpu_usage = current_cpu_usage;
- EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
-
- thread2.Stop();
- current_cpu_usage = metrics->GetCumulativeCPUUsage();
- EXPECT_GE(current_cpu_usage, prev_cpu_usage);
- prev_cpu_usage = current_cpu_usage;
- EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
-
- thread3.Stop();
- current_cpu_usage = metrics->GetCumulativeCPUUsage();
- EXPECT_GE(current_cpu_usage, prev_cpu_usage);
- EXPECT_GE(metrics->GetPlatformIndependentCPUUsage(), 0.0);
-}
-
-#endif // defined(OS_LINUX) || defined(OS_CHROMEOS)
-
-#if defined(OS_CHROMEOS)
-TEST_F(SystemMetricsTest, ParseZramMmStat) {
- SwapInfo swapinfo;
-
- const char invalid_input1[] = "aaa";
- const char invalid_input2[] = "1 2 3 4 5 6";
- const char invalid_input3[] = "a 2 3 4 5 6 7";
- EXPECT_FALSE(ParseZramMmStat(invalid_input1, &swapinfo));
- EXPECT_FALSE(ParseZramMmStat(invalid_input2, &swapinfo));
- EXPECT_FALSE(ParseZramMmStat(invalid_input3, &swapinfo));
-
- const char valid_input1[] =
- "17715200 5008166 566062 0 1225715712 127 183842";
- EXPECT_TRUE(ParseZramMmStat(valid_input1, &swapinfo));
- EXPECT_EQ(17715200ULL, swapinfo.orig_data_size);
- EXPECT_EQ(5008166ULL, swapinfo.compr_data_size);
- EXPECT_EQ(566062ULL, swapinfo.mem_used_total);
-}
-
-TEST_F(SystemMetricsTest, ParseZramStat) {
- SwapInfo swapinfo;
-
- const char invalid_input1[] = "aaa";
- const char invalid_input2[] = "1 2 3 4 5 6 7 8 9 10";
- const char invalid_input3[] = "a 2 3 4 5 6 7 8 9 10 11";
- EXPECT_FALSE(ParseZramStat(invalid_input1, &swapinfo));
- EXPECT_FALSE(ParseZramStat(invalid_input2, &swapinfo));
- EXPECT_FALSE(ParseZramStat(invalid_input3, &swapinfo));
-
- const char valid_input1[] =
- "299 0 2392 0 1 0 8 0 0 0 0";
- EXPECT_TRUE(ParseZramStat(valid_input1, &swapinfo));
- EXPECT_EQ(299ULL, swapinfo.num_reads);
- EXPECT_EQ(1ULL, swapinfo.num_writes);
-}
-#endif // defined(OS_CHROMEOS)
-
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) || \
- defined(OS_ANDROID)
-TEST(SystemMetrics2Test, GetSystemMemoryInfo) {
- SystemMemoryInfoKB info;
- EXPECT_TRUE(GetSystemMemoryInfo(&info));
-
- // Ensure each field received a value.
- EXPECT_GT(info.total, 0);
-#if defined(OS_WIN)
- EXPECT_GT(info.avail_phys, 0);
-#else
- EXPECT_GT(info.free, 0);
-#endif
-#if defined(OS_LINUX) || defined(OS_ANDROID)
- EXPECT_GT(info.buffers, 0);
- EXPECT_GT(info.cached, 0);
- EXPECT_GT(info.active_anon, 0);
- EXPECT_GT(info.inactive_anon, 0);
- EXPECT_GT(info.active_file, 0);
- EXPECT_GT(info.inactive_file, 0);
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
- // All the values should be less than the total amount of memory.
-#if !defined(OS_WIN) && !defined(OS_IOS)
- // TODO(crbug.com/711450): re-enable the following assertion on iOS.
- EXPECT_LT(info.free, info.total);
-#endif
-#if defined(OS_LINUX) || defined(OS_ANDROID)
- EXPECT_LT(info.buffers, info.total);
- EXPECT_LT(info.cached, info.total);
- EXPECT_LT(info.active_anon, info.total);
- EXPECT_LT(info.inactive_anon, info.total);
- EXPECT_LT(info.active_file, info.total);
- EXPECT_LT(info.inactive_file, info.total);
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
-#if defined(OS_MACOSX) || defined(OS_IOS)
- EXPECT_GT(info.file_backed, 0);
-#endif
-
-#if defined(OS_CHROMEOS)
- // Chrome OS exposes shmem.
- EXPECT_GT(info.shmem, 0);
- EXPECT_LT(info.shmem, info.total);
- // Chrome unit tests are not run on actual Chrome OS hardware, so gem_objects
- // and gem_size cannot be tested here.
-#endif
-}
-#endif // defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX) ||
- // defined(OS_ANDROID)
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-TEST(ProcessMetricsTest, ParseProcStatCPU) {
- // /proc/self/stat for a process running "top".
- const char kTopStat[] = "960 (top) S 16230 960 16230 34818 960 "
- "4202496 471 0 0 0 "
- "12 16 0 0 " // <- These are the goods.
- "20 0 1 0 121946157 15077376 314 18446744073709551615 4194304 "
- "4246868 140733983044336 18446744073709551615 140244213071219 "
- "0 0 0 138047495 0 0 0 17 1 0 0 0 0 0";
- EXPECT_EQ(12 + 16, ParseProcStatCPU(kTopStat));
-
- // cat /proc/self/stat on a random other machine I have.
- const char kSelfStat[] = "5364 (cat) R 5354 5364 5354 34819 5364 "
- "0 142 0 0 0 "
- "0 0 0 0 " // <- No CPU, apparently.
- "16 0 1 0 1676099790 2957312 114 4294967295 134512640 134528148 "
- "3221224832 3221224344 3086339742 0 0 0 0 0 0 0 17 0 0 0";
-
- EXPECT_EQ(0, ParseProcStatCPU(kSelfStat));
-
- // Some weird long-running process with a weird name that I created for the
- // purposes of this test.
- const char kWeirdNameStat[] = "26115 (Hello) You ())) ) R 24614 26115 24614"
- " 34839 26115 4218880 227 0 0 0 "
- "5186 11 0 0 "
- "20 0 1 0 36933953 4296704 90 18446744073709551615 4194304 4196116 "
- "140735857761568 140735857761160 4195644 0 0 0 0 0 0 0 17 14 0 0 0 0 0 "
- "6295056 6295616 16519168 140735857770710 140735857770737 "
- "140735857770737 140735857774557 0";
- EXPECT_EQ(5186 + 11, ParseProcStatCPU(kWeirdNameStat));
-}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
-// Disable on Android because base_unittests runs inside a Dalvik VM that
-// starts and stop threads (crbug.com/175563).
-#if defined(OS_LINUX)
-// http://crbug.com/396455
-TEST(ProcessMetricsTest, DISABLED_GetNumberOfThreads) {
- const ProcessHandle current = GetCurrentProcessHandle();
- const int initial_threads = GetNumberOfThreads(current);
- ASSERT_GT(initial_threads, 0);
- const int kNumAdditionalThreads = 10;
- {
- std::unique_ptr<Thread> my_threads[kNumAdditionalThreads];
- for (int i = 0; i < kNumAdditionalThreads; ++i) {
- my_threads[i].reset(new Thread("GetNumberOfThreadsTest"));
- my_threads[i]->Start();
- ASSERT_EQ(GetNumberOfThreads(current), initial_threads + 1 + i);
- }
- }
- // The Thread destructor will stop them.
- ASSERT_EQ(initial_threads, GetNumberOfThreads(current));
-}
-#endif // defined(OS_LINUX)
-
-#if defined(OS_LINUX)
-namespace {
-
-// Keep these in sync so the GetChildOpenFdCount test can refer to correct test
-// main.
-#define ChildMain ChildFdCount
-#define ChildMainString "ChildFdCount"
-
-// Command line flag name and file name used for synchronization.
-const char kTempDirFlag[] = "temp-dir";
-const char kSignalClosed[] = "closed";
-
-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.
-void WaitForEvent(const FilePath& signal_dir, const char* signal_file) {
- while (!CheckEvent(signal_dir, signal_file))
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(10));
-}
-
-// Subprocess to test the number of open file descriptors.
-MULTIPROCESS_TEST_MAIN(ChildMain) {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
- const FilePath temp_path = command_line->GetSwitchValuePath(kTempDirFlag);
- CHECK(DirectoryExists(temp_path));
-
- // Try to close all the file descriptors, so the open count goes to 0.
- for (size_t i = 0; i < 1000; ++i)
- close(i);
- CHECK(SignalEvent(temp_path, kSignalClosed));
-
- // Wait to be terminated.
- while (true)
- PlatformThread::Sleep(TimeDelta::FromSeconds(1));
- return 0;
-}
-
-} // namespace
-
-TEST(ProcessMetricsTest, GetChildOpenFdCount) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- const FilePath temp_path = temp_dir.GetPath();
- CommandLine child_command_line(GetMultiProcessTestChildBaseCommandLine());
- child_command_line.AppendSwitchPath(kTempDirFlag, temp_path);
- Process child = SpawnMultiProcessTestChild(
- ChildMainString, child_command_line, LaunchOptions());
- ASSERT_TRUE(child.IsValid());
- WaitForEvent(temp_path, kSignalClosed);
-
- std::unique_ptr<ProcessMetrics> metrics(
- ProcessMetrics::CreateProcessMetrics(child.Handle()));
- EXPECT_EQ(0, metrics->GetOpenFdCount());
- ASSERT_TRUE(child.Terminate(0, true));
-}
-#endif // defined(OS_LINUX)
-
-#if defined(OS_ANDROID) || defined(OS_LINUX)
-
-TEST(ProcessMetricsTest, GetOpenFdCount) {
- std::unique_ptr<base::ProcessMetrics> metrics(
- base::ProcessMetrics::CreateProcessMetrics(
- base::GetCurrentProcessHandle()));
- int fd_count = metrics->GetOpenFdCount();
- EXPECT_GT(fd_count, 0);
- ScopedFILE file(fopen("/proc/self/statm", "r"));
- EXPECT_TRUE(file);
- int new_fd_count = metrics->GetOpenFdCount();
- EXPECT_GT(new_fd_count, 0);
- EXPECT_EQ(new_fd_count, fd_count + 1);
-}
-
-TEST(ProcessMetricsTestLinux, GetPageFaultCounts) {
- std::unique_ptr<base::ProcessMetrics> process_metrics(
- base::ProcessMetrics::CreateProcessMetrics(
- base::GetCurrentProcessHandle()));
-
- PageFaultCounts counts;
- ASSERT_TRUE(process_metrics->GetPageFaultCounts(&counts));
- ASSERT_GT(counts.minor, 0);
- ASSERT_GE(counts.major, 0);
-
- {
- // Allocate and touch memory. Touching it is required to make sure that the
- // page fault count goes up, as memory is typically mapped lazily.
- const size_t kMappedSize = 4 * (1 << 20);
- SharedMemory memory;
- ASSERT_TRUE(memory.CreateAndMapAnonymous(kMappedSize));
- memset(memory.memory(), 42, kMappedSize);
- memory.Unmap();
- }
-
- PageFaultCounts counts_after;
- ASSERT_TRUE(process_metrics->GetPageFaultCounts(&counts_after));
- ASSERT_GT(counts_after.minor, counts.minor);
- ASSERT_GE(counts_after.major, counts.major);
-}
-#endif // defined(OS_ANDROID) || defined(OS_LINUX)
-
-} // namespace debug
-} // namespace base
diff --git a/base/process/process_unittest.cc b/base/process/process_unittest.cc
deleted file mode 100644
index 0f05d24..0000000
--- 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_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 implementation actually ignores 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 81c31b2..0000000
--- a/base/process/process_util_unittest.cc
+++ /dev/null
@@ -1,1140 +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_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) || defined(OS_FUCHSIA)
-#include <dlfcn.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <sched.h>
-#include <signal.h>
-#include <sys/socket.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <unistd.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 <fdio/limits.h>
-#include <zircon/process.h>
-#include <zircon/processargs.h>
-#include <zircon/syscalls.h>
-#include "base/base_paths_fuchsia.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) || defined(OS_FUCHSIA)
-const char kSignalFileTerm[] = "TerminatedChildProcess.die";
-#endif
-
-#if defined(OS_FUCHSIA)
-const char kSignalFileClone[] = "ClonedTmpDir.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(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, SelectivelyClonedDir) {
- const std::string signal_file =
- ProcessUtilTest::GetSignalFilePath(kSignalFileClone);
- remove(signal_file.c_str());
-
- LaunchOptions options;
- options.paths_to_map.push_back(base::FilePath("/tmp"));
- options.clone_flags = LP_CLONE_FDIO_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);
-}
-
-// 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_map.push_back(base::FilePath("/tmp"));
- options.paths_to_map.push_back(base::FilePath("/data"));
- options.clone_flags = LP_CLONE_FDIO_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);
-}
-
-#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) || defined(OS_FUCHSIA)
- // 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)
-#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) || defined(OS_FUCHSIA)
- 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) || defined(OS_FUCHSIA)
- // Send a SIGKILL to this process, just like the OOM killer would.
- ::kill(getpid(), SIGKILL);
-#endif
- return 1;
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-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)
-
-TEST_F(ProcessUtilTest, 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) || defined(OS_FUCHSIA)
- 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) || defined(OS_FUCHSIA)
-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) || defined(OS_FUCHSIA)
-
-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());
-
- // Allow a generous timeout, to cope with slow/loaded test bots.
- EXPECT_TRUE(child_process.WaitForExitWithTimeout(
- TestTimeouts::action_max_timeout(), nullptr));
-}
-
-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_get_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/stack_sampling_profiler_unittest.cc b/base/profiler/stack_sampling_profiler_unittest.cc
deleted file mode 100644
index b25943f..0000000
--- a/base/profiler/stack_sampling_profiler_unittest.cc
+++ /dev/null
@@ -1,1506 +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/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/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "base/time/time.h"
-#include "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<StackSamplingProfiler::Frame>;
-using Module = StackSamplingProfiler::Module;
-using Sample = StackSamplingProfiler::Sample;
-using CallStackProfile = StackSamplingProfiler::CallStackProfile;
-using CallStackProfiles = StackSamplingProfiler::CallStackProfiles;
-
-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
-}
-
-// 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
-}
-
-// Called on the profiler thread when complete, to collect profiles.
-void SaveProfiles(CallStackProfiles* profiles,
- CallStackProfiles pending_profiles) {
- *profiles = std::move(pending_profiles);
-}
-
-// Called on the profiler thread when complete. Collects profiles produced by
-// the profiler, and signals an event to allow the main thread to know that that
-// the profiler is done.
-void SaveProfilesAndSignalEvent(CallStackProfiles* profiles,
- WaitableEvent* event,
- CallStackProfiles pending_profiles) {
- *profiles = std::move(pending_profiles);
- event->Signal();
-}
-
-// 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,
- Bind(&SaveProfilesAndSignalEvent,
- Unretained(&profiles),
- Unretained(&completed)),
- delegate) {}
-
- // The order here is important to ensure objects being referenced don't get
- // destructed until after the objects referencing them.
- CallStackProfiles profiles;
- 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 profiles as specified by |params| on the TargetThread, and returns
-// them in |profiles|. Waits up to |profiler_wait_time| for the profiler to
-// complete.
-void CaptureProfiles(const SamplingParams& params, TimeDelta profiler_wait_time,
- CallStackProfiles* profiles) {
- WithTargetThread([¶ms, profiles,
- 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();
-
- *profiles = std::move(info.profiles);
- });
-}
-
-// 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.
-Frames::const_iterator FindFirstFrameWithinFunction(
- const Sample& sample,
- 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 = sample.frames.begin(); it != sample.frames.end(); ++it) {
- if ((it->instruction_pointer >= function_start) &&
- (it->instruction_pointer <= function_end))
- return it;
- }
- return sample.frames.end();
-}
-
-// Formats a sample into a string that can be output for test diagnostics.
-std::string FormatSampleForDiagnosticOutput(
- const Sample& sample,
- const std::vector<Module>& modules) {
- std::string output;
- for (const Frame& frame : sample.frames) {
- output += StringPrintf(
- "0x%p %s\n", reinterpret_cast<const void*>(frame.instruction_pointer),
- modules[frame.module_index].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_burst = 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);
- std::vector<CallStackProfile> profiles;
- const StackSamplingProfiler::CompletedCallback callback =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles),
- Unretained(&sampling_thread_completed));
- 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, callback,
- &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 |profiles|.
- sampling_thread_completed.Wait();
-
- // Look up the sample.
- ASSERT_EQ(1u, profiles.size());
- const CallStackProfile& profile = profiles[0];
- ASSERT_EQ(1u, profile.samples.size());
- const Sample& sample = profile.samples[0];
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- Frames::const_iterator end_frame = FindFirstFrameWithinFunction(
- sample, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(end_frame != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
- 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, sample.frames.end() - end_frame)
- << "Stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
- } 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 (sample.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().
- Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction(
- sample, &TargetThread::CallThroughOtherLibrary);
- ASSERT_TRUE(other_library_frame != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::CallThroughOtherLibrary))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
- // 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(sample, profile.modules);
- }
-}
-
-// 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 a sampled call stack
-// profile.
-// 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_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
-
- // Check that the profile and samples sizes are correct, and the module
- // indices are in range.
- ASSERT_EQ(1u, profiles.size());
- const CallStackProfile& profile = profiles[0];
- ASSERT_EQ(1u, profile.samples.size());
- EXPECT_EQ(params.sampling_interval, profile.sampling_period);
- const Sample& sample = profile.samples[0];
- EXPECT_EQ(0u, sample.process_milestones);
- for (const auto& frame : sample.frames) {
- ASSERT_GE(frame.module_index, 0u);
- ASSERT_LT(frame.module_index, profile.modules.size());
- }
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled() and that the frame has this
- // executable's module.
- Frames::const_iterator loc = FindFirstFrameWithinFunction(
- sample, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(loc != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
- FilePath executable_path;
- EXPECT_TRUE(PathService::Get(FILE_EXE, &executable_path));
- EXPECT_EQ(executable_path,
- MakeAbsoluteFilePath(profile.modules[loc->module_index].filename));
-}
-
-// Checks that annotations are recorded in samples.
-PROFILER_TEST_F(StackSamplingProfilerTest, Annotations) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_burst = 1;
-
- // Check that a run picks up annotations.
- StackSamplingProfiler::SetProcessMilestone(1);
- std::vector<CallStackProfile> profiles1;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles1);
- ASSERT_EQ(1u, profiles1.size());
- const CallStackProfile& profile1 = profiles1[0];
- ASSERT_EQ(1u, profile1.samples.size());
- const Sample& sample1 = profile1.samples[0];
- EXPECT_EQ(1u << 1, sample1.process_milestones);
-
- // Run it a second time but with changed annotations. These annotations
- // should appear in the first acquired sample.
- StackSamplingProfiler::SetProcessMilestone(2);
- std::vector<CallStackProfile> profiles2;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles2);
- ASSERT_EQ(1u, profiles2.size());
- const CallStackProfile& profile2 = profiles2[0];
- ASSERT_EQ(1u, profile2.samples.size());
- const Sample& sample2 = profile2.samples[0];
- EXPECT_EQ(sample1.process_milestones | (1u << 2), sample2.process_milestones);
-}
-
-// 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_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- WithTargetThread(
- [¶ms, &profiles](PlatformThreadId target_thread_id) {
- WaitableEvent sampling_thread_completed(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- const StackSamplingProfiler::CompletedCallback callback =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles),
- Unretained(&sampling_thread_completed));
- StackSamplingProfiler profiler(target_thread_id, params, callback);
- profiler.Start();
- sampling_thread_completed.Wait();
- },
- StackConfiguration(StackConfiguration::WITH_ALLOCA));
-
- // Look up the sample.
- ASSERT_EQ(1u, profiles.size());
- const CallStackProfile& profile = profiles[0];
- ASSERT_EQ(1u, profile.samples.size());
- const Sample& sample = profile.samples[0];
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- Frames::const_iterator end_frame = FindFirstFrameWithinFunction(
- sample, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(end_frame != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
- // Check that the stack contains a frame for TargetThread::CallWithAlloca().
- Frames::const_iterator alloca_frame =
- FindFirstFrameWithinFunction(sample, &TargetThread::CallWithAlloca);
- ASSERT_TRUE(alloca_frame != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(
- reinterpret_cast<const void*>(&TargetThread::CallWithAlloca))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
- // These frames should be adjacent on the stack.
- EXPECT_EQ(1, alloca_frame - end_frame)
- << "Stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-}
-
-// Checks that the expected number of profiles and samples are present in the
-// call stack profiles produced.
-PROFILER_TEST_F(StackSamplingProfilerTest, MultipleProfilesAndSamples) {
- SamplingParams params;
- params.burst_interval = params.sampling_interval =
- TimeDelta::FromMilliseconds(0);
- params.bursts = 2;
- params.samples_per_burst = 3;
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
-
- ASSERT_EQ(2u, profiles.size());
- EXPECT_EQ(3u, profiles[0].samples.size());
- EXPECT_EQ(3u, profiles[1].samples.size());
-}
-
-// 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_burst = 1;
-
- CallStackProfiles profiles;
- WaitableEvent sampling_completed(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- const StackSamplingProfiler::CompletedCallback callback =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles),
- Unretained(&sampling_completed));
- StackSamplingProfiler profiler(target_thread_id, params, callback);
-
- 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_burst = 100000;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(10);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_burst = 100000;
-
- SampleRecordedCounter samples_recorded[arraysize(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
- // PerformCollectionTask 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 PerformCollectionTask 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 call stack profiles are captured if the profiling is stopped
-// during the initial delay.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInitialDelay) {
- SamplingParams params;
- params.initial_delay = TimeDelta::FromSeconds(60);
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, TimeDelta::FromMilliseconds(0), &profiles);
-
- EXPECT_TRUE(profiles.empty());
-}
-
-// Checks that the single completed call stack profile is captured if the
-// profiling is stopped between bursts.
-PROFILER_TEST_F(StackSamplingProfilerTest, StopDuringInterBurstInterval) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.burst_interval = TimeDelta::FromSeconds(60);
- params.bursts = 2;
- params.samples_per_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, TimeDelta::FromMilliseconds(50), &profiles);
-
- ASSERT_EQ(1u, profiles.size());
- EXPECT_EQ(1u, profiles[0].samples.size());
-}
-
-// Checks that tasks can be stopped before completion and incomplete call stack
-// profiles 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_burst = 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();
-
- ASSERT_EQ(1u, profiler_info.profiles.size());
- EXPECT_EQ(1u, profiler_info.profiles[0].samples.size());
- });
-}
-
-// Checks that we can destroy the profiler while profiling.
-PROFILER_TEST_F(StackSamplingProfilerTest, DestroyProfilerWhileProfiling) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(10);
-
- CallStackProfiles profiles;
- WithTargetThread([¶ms, &profiles](PlatformThreadId target_thread_id) {
- std::unique_ptr<StackSamplingProfiler> profiler;
- profiler.reset(new StackSamplingProfiler(
- target_thread_id, params, Bind(&SaveProfiles, Unretained(&profiles))));
- 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 same profiler may be run multiple times.
-PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleTimes) {
- WithTargetThread([](PlatformThreadId target_thread_id) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_burst = 1;
-
- CallStackProfiles profiles;
- WaitableEvent sampling_completed(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- const StackSamplingProfiler::CompletedCallback callback =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles),
- Unretained(&sampling_completed));
- StackSamplingProfiler profiler(target_thread_id, params, callback);
-
- // Just start and stop to execute code paths.
- profiler.Start();
- profiler.Stop();
- sampling_completed.Wait();
-
- // Ensure a second request will run and not block.
- sampling_completed.Reset();
- profiles.clear();
- profiler.Start();
- sampling_completed.Wait();
- profiler.Stop();
- ASSERT_EQ(1u, profiles.size());
- });
-}
-
-// Checks that the different profilers may be run.
-PROFILER_TEST_F(StackSamplingProfilerTest, CanRunMultipleProfilers) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
- ASSERT_EQ(1u, profiles.size());
-
- profiles.clear();
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
- ASSERT_EQ(1u, profiles.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_burst = 1;
-
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_burst = 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]->profiles.size());
- });
-}
-
-// Checks that the sampling thread can shut down.
-PROFILER_TEST_F(StackSamplingProfilerTest, SamplerIdleShutdown) {
- SamplingParams params;
- params.sampling_interval = TimeDelta::FromMilliseconds(0);
- params.samples_per_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
- ASSERT_EQ(1u, profiles.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(base::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_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
- ASSERT_EQ(1u, profiles.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.
- profiles.clear();
- CaptureProfiles(params, AVeryLongTimeDelta(), &profiles);
- ASSERT_EQ(1u, profiles.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_burst = 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_burst = 1;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(0);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_burst = 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_burst = 1;
-
- TestProfilerInfo profiler_info(target_thread_id, params);
-
- profiler_info.profiler.Start();
- profiler_info.completed.Wait();
- EXPECT_EQ(1u, profiler_info.profiles.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(base::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.profiles.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_burst = 9;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(11);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(1);
- params[1].samples_per_burst = 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);
- ASSERT_EQ(1u, profiler_infos[completed_profiler]->profiles.size());
-
- size_t other_profiler = 1 - completed_profiler;
- // Wait for the other profiler to finish.
- profiler_infos[other_profiler]->completed.Wait();
- ASSERT_EQ(1u, profiler_infos[other_profiler]->profiles.size());
-
- // Ensure each got the correct number of samples.
- EXPECT_EQ(9u, profiler_infos[0]->profiles[0].samples.size());
- EXPECT_EQ(8u, profiler_infos[1]->profiles[0].samples.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_burst = 10;
-
- params[1].initial_delay = TimeDelta::FromMilliseconds(9);
- params[1].sampling_interval = TimeDelta::FromMilliseconds(3);
- params[1].samples_per_burst = 10;
-
- params[2].initial_delay = TimeDelta::FromMilliseconds(10);
- params[2].sampling_interval = TimeDelta::FromMilliseconds(2);
- params[2].samples_per_burst = 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(1u, profiler_infos[completed_profiler]->profiles.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_burst = 1;
-
- std::vector<CallStackProfile> profiles;
- {
- ScopedNativeLibrary other_library(LoadOtherLibrary());
- WithTargetThread(
- [¶ms, &profiles](PlatformThreadId target_thread_id) {
- WaitableEvent sampling_thread_completed(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- const StackSamplingProfiler::CompletedCallback callback =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles),
- Unretained(&sampling_thread_completed));
- StackSamplingProfiler profiler(target_thread_id, params, callback);
- profiler.Start();
- sampling_thread_completed.Wait();
- },
- StackConfiguration(StackConfiguration::WITH_OTHER_LIBRARY,
- other_library.get()));
- }
-
- // Look up the sample.
- ASSERT_EQ(1u, profiles.size());
- const CallStackProfile& profile = profiles[0];
- ASSERT_EQ(1u, profile.samples.size());
- const Sample& sample = profile.samples[0];
-
- // Check that the stack contains a frame for
- // TargetThread::CallThroughOtherLibrary().
- Frames::const_iterator other_library_frame = FindFirstFrameWithinFunction(
- sample, &TargetThread::CallThroughOtherLibrary);
- ASSERT_TRUE(other_library_frame != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::CallThroughOtherLibrary))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
- // Check that the stack contains a frame for
- // TargetThread::SignalAndWaitUntilSignaled().
- Frames::const_iterator end_frame = FindFirstFrameWithinFunction(
- sample, &TargetThread::SignalAndWaitUntilSignaled);
- ASSERT_TRUE(end_frame != sample.frames.end())
- << "Function at "
- << MaybeFixupFunctionAddressForILT(reinterpret_cast<const void*>(
- &TargetThread::SignalAndWaitUntilSignaled))
- << " was not found in stack:\n"
- << FormatSampleForDiagnosticOutput(sample, profile.modules);
-
- // 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(sample, profile.modules);
-}
-
-// 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_burst = 9;
- params2.initial_delay = TimeDelta::FromMilliseconds(10);
- params2.sampling_interval = TimeDelta::FromMilliseconds(1);
- params2.samples_per_burst = 8;
-
- std::vector<CallStackProfile> profiles1, profiles2;
-
- WaitableEvent sampling_thread_completed1(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- const StackSamplingProfiler::CompletedCallback callback1 =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles1),
- Unretained(&sampling_thread_completed1));
- StackSamplingProfiler profiler1(target_thread1.id(), params1, callback1);
-
- WaitableEvent sampling_thread_completed2(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- const StackSamplingProfiler::CompletedCallback callback2 =
- Bind(&SaveProfilesAndSignalEvent, Unretained(&profiles2),
- Unretained(&sampling_thread_completed2));
- StackSamplingProfiler profiler2(target_thread2.id(), params2, callback2);
-
- // Finally the real work.
- profiler1.Start();
- profiler2.Start();
- sampling_thread_completed1.Wait();
- sampling_thread_completed2.Wait();
- ASSERT_EQ(1u, profiles1.size());
- EXPECT_EQ(9u, profiles1[0].samples.size());
- ASSERT_EQ(1u, profiles2.size());
- EXPECT_EQ(8u, profiles2[0].samples.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,
- Bind(&SaveProfilesAndSignalEvent,
- Unretained(&profiles_),
- Unretained(&completed_))) {}
-
- void Run() override {
- run_.Wait();
- profiler_.Start();
- }
-
- void Go() { run_.Signal(); }
-
- void Wait() { completed_.Wait(); }
-
- CallStackProfiles& profiles() { return profiles_; }
-
- private:
- WaitableEvent run_;
-
- CallStackProfiles profiles_;
- 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_burst = 9;
- params2.initial_delay = TimeDelta::FromMilliseconds(10);
- params2.sampling_interval = TimeDelta::FromMilliseconds(1);
- params2.samples_per_burst = 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(base::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();
- ASSERT_EQ(1u, profiler_thread1.profiles().size());
- EXPECT_EQ(9u, profiler_thread1.profiles()[0].samples.size());
- ASSERT_EQ(1u, profiler_thread2.profiles().size());
- EXPECT_EQ(8u, profiler_thread2.profiles()[0].samples.size());
-
- profiler_thread1.Join();
- profiler_thread2.Join();
- });
-}
-
-} // namespace base
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 cecfe22..0000000
--- 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/rand_util_unittest.cc b/base/rand_util_unittest.cc
deleted file mode 100644
index 11a118a..0000000
--- a/base/rand_util_unittest.cc
+++ /dev/null
@@ -1,170 +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/rand_util.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-const int kIntMin = std::numeric_limits<int>::min();
-const int kIntMax = std::numeric_limits<int>::max();
-
-} // namespace
-
-TEST(RandUtilTest, RandInt) {
- EXPECT_EQ(base::RandInt(0, 0), 0);
- EXPECT_EQ(base::RandInt(kIntMin, kIntMin), kIntMin);
- EXPECT_EQ(base::RandInt(kIntMax, kIntMax), kIntMax);
-
- // Check that the DCHECKS in RandInt() don't fire due to internal overflow.
- // There was a 50% chance of that happening, so calling it 40 times means
- // the chances of this passing by accident are tiny (9e-13).
- for (int i = 0; i < 40; ++i)
- base::RandInt(kIntMin, kIntMax);
-}
-
-TEST(RandUtilTest, RandDouble) {
- // Force 64-bit precision, making sure we're not in a 80-bit FPU register.
- volatile double number = base::RandDouble();
- EXPECT_GT(1.0, number);
- EXPECT_LE(0.0, number);
-}
-
-TEST(RandUtilTest, RandBytes) {
- const size_t buffer_size = 50;
- char buffer[buffer_size];
- memset(buffer, 0, buffer_size);
- base::RandBytes(buffer, buffer_size);
- std::sort(buffer, buffer + buffer_size);
- // Probability of occurrence of less than 25 unique bytes in 50 random bytes
- // is below 10^-25.
- EXPECT_GT(std::unique(buffer, buffer + buffer_size) - buffer, 25);
-}
-
-// Verify that calling base::RandBytes with an empty buffer doesn't fail.
-TEST(RandUtilTest, RandBytes0) {
- base::RandBytes(nullptr, 0);
-}
-
-TEST(RandUtilTest, RandBytesAsString) {
- std::string random_string = base::RandBytesAsString(1);
- EXPECT_EQ(1U, random_string.size());
- random_string = base::RandBytesAsString(145);
- EXPECT_EQ(145U, random_string.size());
- char accumulator = 0;
- for (size_t i = 0; i < random_string.size(); ++i)
- accumulator |= random_string[i];
- // In theory this test can fail, but it won't before the universe dies of
- // heat death.
- EXPECT_NE(0, accumulator);
-}
-
-// Make sure that it is still appropriate to use RandGenerator in conjunction
-// with std::random_shuffle().
-TEST(RandUtilTest, RandGeneratorForRandomShuffle) {
- EXPECT_EQ(base::RandGenerator(1), 0U);
- EXPECT_LE(std::numeric_limits<ptrdiff_t>::max(),
- std::numeric_limits<int64_t>::max());
-}
-
-TEST(RandUtilTest, RandGeneratorIsUniform) {
- // Verify that RandGenerator has a uniform distribution. This is a
- // regression test that consistently failed when RandGenerator was
- // implemented this way:
- //
- // return base::RandUint64() % max;
- //
- // A degenerate case for such an implementation is e.g. a top of
- // range that is 2/3rds of the way to MAX_UINT64, in which case the
- // bottom half of the range would be twice as likely to occur as the
- // top half. A bit of calculus care of jar@ shows that the largest
- // measurable delta is when the top of the range is 3/4ths of the
- // way, so that's what we use in the test.
- const uint64_t kTopOfRange =
- (std::numeric_limits<uint64_t>::max() / 4ULL) * 3ULL;
- const uint64_t kExpectedAverage = kTopOfRange / 2ULL;
- const uint64_t kAllowedVariance = kExpectedAverage / 50ULL; // +/- 2%
- const int kMinAttempts = 1000;
- const int kMaxAttempts = 1000000;
-
- double cumulative_average = 0.0;
- int count = 0;
- while (count < kMaxAttempts) {
- uint64_t value = base::RandGenerator(kTopOfRange);
- cumulative_average = (count * cumulative_average + value) / (count + 1);
-
- // Don't quit too quickly for things to start converging, or we may have
- // a false positive.
- if (count > kMinAttempts &&
- kExpectedAverage - kAllowedVariance < cumulative_average &&
- cumulative_average < kExpectedAverage + kAllowedVariance) {
- break;
- }
-
- ++count;
- }
-
- ASSERT_LT(count, kMaxAttempts) << "Expected average was " <<
- kExpectedAverage << ", average ended at " << cumulative_average;
-}
-
-TEST(RandUtilTest, RandUint64ProducesBothValuesOfAllBits) {
- // This tests to see that our underlying random generator is good
- // enough, for some value of good enough.
- uint64_t kAllZeros = 0ULL;
- uint64_t kAllOnes = ~kAllZeros;
- uint64_t found_ones = kAllZeros;
- uint64_t found_zeros = kAllOnes;
-
- for (size_t i = 0; i < 1000; ++i) {
- uint64_t value = base::RandUint64();
- found_ones |= value;
- found_zeros &= value;
-
- if (found_zeros == kAllZeros && found_ones == kAllOnes)
- return;
- }
-
- FAIL() << "Didn't achieve all bit values in maximum number of tries.";
-}
-
-TEST(RandUtilTest, RandBytesLonger) {
- // Fuchsia can only retrieve 256 bytes of entropy at a time, so make sure we
- // handle longer requests than that.
- std::string random_string0 = base::RandBytesAsString(255);
- EXPECT_EQ(255u, random_string0.size());
- std::string random_string1 = base::RandBytesAsString(1023);
- EXPECT_EQ(1023u, random_string1.size());
- std::string random_string2 = base::RandBytesAsString(4097);
- EXPECT_EQ(4097u, random_string2.size());
-}
-
-// Benchmark test for RandBytes(). Disabled since it's intentionally slow and
-// does not test anything that isn't already tested by the existing RandBytes()
-// tests.
-TEST(RandUtilTest, DISABLED_RandBytesPerf) {
- // Benchmark the performance of |kTestIterations| of RandBytes() using a
- // buffer size of |kTestBufferSize|.
- const int kTestIterations = 10;
- const size_t kTestBufferSize = 1 * 1024 * 1024;
-
- std::unique_ptr<uint8_t[]> buffer(new uint8_t[kTestBufferSize]);
- const base::TimeTicks now = base::TimeTicks::Now();
- for (int i = 0; i < kTestIterations; ++i)
- base::RandBytes(buffer.get(), kTestBufferSize);
- const base::TimeTicks end = base::TimeTicks::Now();
-
- LOG(INFO) << "RandBytes(" << kTestBufferSize << ") took: "
- << (end - now).InMicroseconds() << "µs";
-}
diff --git a/base/run_loop_unittest.cc b/base/run_loop_unittest.cc
deleted file mode 100644
index 3564a2e..0000000
--- 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_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 7fcc5d1..0000000
--- 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_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/sampling_heap_profiler/sampling_heap_profiler_unittest.cc b/base/sampling_heap_profiler/sampling_heap_profiler_unittest.cc
deleted file mode 100644
index d3bef90..0000000
--- a/base/sampling_heap_profiler/sampling_heap_profiler_unittest.cc
+++ /dev/null
@@ -1,165 +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/sampling_heap_profiler/sampling_heap_profiler.h"
-
-#include <stdlib.h>
-#include <cinttypes>
-
-#include "base/allocator/allocator_shim.h"
-#include "base/debug/alias.h"
-#include "base/threading/simple_thread.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-class SamplingHeapProfilerTest : public ::testing::Test {
-#if defined(OS_MACOSX)
- void SetUp() override { allocator::InitializeAllocatorShim(); }
-#endif
-};
-
-class SamplesCollector : public SamplingHeapProfiler::SamplesObserver {
- public:
- explicit SamplesCollector(size_t watch_size) : watch_size_(watch_size) {}
-
- void SampleAdded(uint32_t id, size_t size, size_t) override {
- if (sample_added || size != watch_size_)
- return;
- sample_id_ = id;
- sample_added = true;
- }
-
- void SampleRemoved(uint32_t id) override {
- if (id == sample_id_)
- sample_removed = true;
- }
-
- bool sample_added = false;
- bool sample_removed = false;
-
- private:
- size_t watch_size_;
- uint32_t sample_id_ = 0;
-};
-
-TEST_F(SamplingHeapProfilerTest, CollectSamples) {
- SamplingHeapProfiler::InitTLSSlot();
- SamplesCollector collector(10000);
- SamplingHeapProfiler* profiler = SamplingHeapProfiler::GetInstance();
- profiler->SuppressRandomnessForTest(true);
- profiler->SetSamplingInterval(1024);
- profiler->Start();
- profiler->AddSamplesObserver(&collector);
- void* volatile p = malloc(10000);
- free(p);
- profiler->Stop();
- profiler->RemoveSamplesObserver(&collector);
- CHECK(collector.sample_added);
- CHECK(collector.sample_removed);
-}
-
-const int kNumberOfAllocations = 10000;
-
-NOINLINE void Allocate1() {
- void* p = malloc(400);
- base::debug::Alias(&p);
-}
-
-NOINLINE void Allocate2() {
- void* p = malloc(700);
- base::debug::Alias(&p);
-}
-
-NOINLINE void Allocate3() {
- void* p = malloc(20480);
- base::debug::Alias(&p);
-}
-
-class MyThread1 : public SimpleThread {
- public:
- MyThread1() : SimpleThread("MyThread1") {}
- void Run() override {
- for (int i = 0; i < kNumberOfAllocations; ++i)
- Allocate1();
- }
-};
-
-class MyThread2 : public SimpleThread {
- public:
- MyThread2() : SimpleThread("MyThread2") {}
- void Run() override {
- for (int i = 0; i < kNumberOfAllocations; ++i)
- Allocate2();
- }
-};
-
-void CheckAllocationPattern(void (*allocate_callback)()) {
- SamplingHeapProfiler::InitTLSSlot();
- SamplingHeapProfiler* profiler = SamplingHeapProfiler::GetInstance();
- profiler->SuppressRandomnessForTest(false);
- profiler->SetSamplingInterval(10240);
- base::TimeTicks t0 = base::TimeTicks::Now();
- std::map<size_t, size_t> sums;
- const int iterations = 40;
- for (int i = 0; i < iterations; ++i) {
- uint32_t id = profiler->Start();
- allocate_callback();
- std::vector<SamplingHeapProfiler::Sample> samples =
- profiler->GetSamples(id);
- profiler->Stop();
- std::map<size_t, size_t> buckets;
- for (auto& sample : samples) {
- buckets[sample.size] += sample.total;
- }
- for (auto& it : buckets) {
- if (it.first != 400 && it.first != 700 && it.first != 20480)
- continue;
- sums[it.first] += it.second;
- printf("%zu,", it.second);
- }
- printf("\n");
- }
-
- printf("Time taken %" PRIu64 "ms\n",
- (base::TimeTicks::Now() - t0).InMilliseconds());
-
- for (auto sum : sums) {
- intptr_t expected = sum.first * kNumberOfAllocations;
- intptr_t actual = sum.second / iterations;
- printf("%zu:\tmean: %zu\trelative error: %.2f%%\n", sum.first, actual,
- 100. * (actual - expected) / expected);
- }
-}
-
-// Manual tests to check precision of the sampling profiler.
-// Yes, they do leak lots of memory.
-
-TEST_F(SamplingHeapProfilerTest, DISABLED_ParallelLargeSmallStats) {
- CheckAllocationPattern([]() {
- SimpleThread* t1 = new MyThread1();
- SimpleThread* t2 = new MyThread2();
- t1->Start();
- t2->Start();
- for (int i = 0; i < kNumberOfAllocations; ++i)
- Allocate3();
- t1->Join();
- t2->Join();
- });
-}
-
-TEST_F(SamplingHeapProfilerTest, DISABLED_SequentialLargeSmallStats) {
- CheckAllocationPattern([]() {
- for (int i = 0; i < kNumberOfAllocations; ++i) {
- Allocate1();
- Allocate2();
- Allocate3();
- }
- });
-}
-
-} // namespace
-} // namespace base
diff --git a/base/scoped_clear_errno_unittest.cc b/base/scoped_clear_errno_unittest.cc
deleted file mode 100644
index 8afb33e..0000000
--- a/base/scoped_clear_errno_unittest.cc
+++ /dev/null
@@ -1,30 +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 <errno.h>
-
-#include "base/scoped_clear_errno.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(ScopedClearErrno, TestNoError) {
- errno = 1;
- {
- ScopedClearErrno clear_error;
- EXPECT_EQ(0, errno);
- }
- EXPECT_EQ(1, errno);
-}
-
-TEST(ScopedClearErrno, TestError) {
- errno = 1;
- {
- ScopedClearErrno clear_error;
- errno = 2;
- }
- EXPECT_EQ(2, errno);
-}
-
-} // namespace base
diff --git a/base/scoped_generic_unittest.cc b/base/scoped_generic_unittest.cc
deleted file mode 100644
index 5a6abfb..0000000
--- a/base/scoped_generic_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/scoped_generic.h"
-
-#include <utility>
-#include <vector>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-struct IntTraits {
- IntTraits(std::vector<int>* freed) : freed_ints(freed) {}
-
- static int InvalidValue() {
- return -1;
- }
- void Free(int value) {
- freed_ints->push_back(value);
- }
-
- std::vector<int>* freed_ints;
-};
-
-typedef ScopedGeneric<int, IntTraits> ScopedInt;
-
-} // namespace
-
-TEST(ScopedGenericTest, ScopedGeneric) {
- std::vector<int> values_freed;
- IntTraits traits(&values_freed);
-
- // Invalid case, delete should not be called.
- {
- ScopedInt a(IntTraits::InvalidValue(), traits);
- }
- EXPECT_TRUE(values_freed.empty());
-
- // Simple deleting case.
- static const int kFirst = 0;
- {
- ScopedInt a(kFirst, traits);
- }
- ASSERT_EQ(1u, values_freed.size());
- ASSERT_EQ(kFirst, values_freed[0]);
- values_freed.clear();
-
- // Release should return the right value and leave the object empty.
- {
- ScopedInt a(kFirst, traits);
- EXPECT_EQ(kFirst, a.release());
-
- ScopedInt b(IntTraits::InvalidValue(), traits);
- EXPECT_EQ(IntTraits::InvalidValue(), b.release());
- }
- ASSERT_TRUE(values_freed.empty());
-
- // Reset should free the old value, then the new one should go away when
- // it goes out of scope.
- static const int kSecond = 1;
- {
- ScopedInt b(kFirst, traits);
- b.reset(kSecond);
- ASSERT_EQ(1u, values_freed.size());
- ASSERT_EQ(kFirst, values_freed[0]);
- }
- ASSERT_EQ(2u, values_freed.size());
- ASSERT_EQ(kSecond, values_freed[1]);
- values_freed.clear();
-
- // Swap.
- {
- ScopedInt a(kFirst, traits);
- ScopedInt b(kSecond, traits);
- a.swap(b);
- EXPECT_TRUE(values_freed.empty()); // Nothing should be freed.
- EXPECT_EQ(kSecond, a.get());
- EXPECT_EQ(kFirst, b.get());
- }
- // Values should be deleted in the opposite order.
- ASSERT_EQ(2u, values_freed.size());
- EXPECT_EQ(kFirst, values_freed[0]);
- EXPECT_EQ(kSecond, values_freed[1]);
- values_freed.clear();
-
- // Move constructor.
- {
- ScopedInt a(kFirst, traits);
- ScopedInt b(std::move(a));
- EXPECT_TRUE(values_freed.empty()); // Nothing should be freed.
- ASSERT_EQ(IntTraits::InvalidValue(), a.get());
- ASSERT_EQ(kFirst, b.get());
- }
-
- ASSERT_EQ(1u, values_freed.size());
- ASSERT_EQ(kFirst, values_freed[0]);
- values_freed.clear();
-
- // Move assign.
- {
- ScopedInt a(kFirst, traits);
- ScopedInt b(kSecond, traits);
- b = std::move(a);
- ASSERT_EQ(1u, values_freed.size());
- EXPECT_EQ(kSecond, values_freed[0]);
- ASSERT_EQ(IntTraits::InvalidValue(), a.get());
- ASSERT_EQ(kFirst, b.get());
- }
-
- ASSERT_EQ(2u, values_freed.size());
- EXPECT_EQ(kFirst, values_freed[1]);
- values_freed.clear();
-}
-
-TEST(ScopedGenericTest, Operators) {
- std::vector<int> values_freed;
- IntTraits traits(&values_freed);
-
- static const int kFirst = 0;
- static const int kSecond = 1;
- {
- ScopedInt a(kFirst, traits);
- EXPECT_TRUE(a == kFirst);
- EXPECT_FALSE(a != kFirst);
- EXPECT_FALSE(a == kSecond);
- EXPECT_TRUE(a != kSecond);
-
- EXPECT_TRUE(kFirst == a);
- EXPECT_FALSE(kFirst != a);
- EXPECT_FALSE(kSecond == a);
- EXPECT_TRUE(kSecond != a);
- }
-
- // is_valid().
- {
- ScopedInt a(kFirst, traits);
- EXPECT_TRUE(a.is_valid());
- a.reset();
- EXPECT_FALSE(a.is_valid());
- }
-}
-
-// Cheesy manual "no compile" test for manually validating changes.
-#if 0
-TEST(ScopedGenericTest, NoCompile) {
- // Assignment shouldn't work.
- /*{
- ScopedInt a(kFirst, traits);
- ScopedInt b(a);
- }*/
-
- // Comparison shouldn't work.
- /*{
- ScopedInt a(kFirst, traits);
- ScopedInt b(kFirst, traits);
- if (a == b) {
- }
- }*/
-
- // Implicit conversion to bool shouldn't work.
- /*{
- ScopedInt a(kFirst, traits);
- bool result = a;
- }*/
-}
-#endif
-
-} // namespace base
diff --git a/base/scoped_native_library_unittest.cc b/base/scoped_native_library_unittest.cc
deleted file mode 100644
index 261e9d1..0000000
--- 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_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/security_unittest.cc b/base/security_unittest.cc
deleted file mode 100644
index 9a3bc27..0000000
--- a/base/security_unittest.cc
+++ /dev/null
@@ -1,172 +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 <fcntl.h>
-#include <stddef.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-
-#include <algorithm>
-#include <limits>
-#include <memory>
-
-#include "base/files/file_util.h"
-#include "base/logging.h"
-#include "base/memory/free_deleter.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <sys/mman.h>
-#include <unistd.h>
-#endif
-
-using std::nothrow;
-using std::numeric_limits;
-
-namespace {
-
-// This function acts as a compiler optimization barrier. We use it to
-// prevent the compiler from making an expression a compile-time constant.
-// We also use it so that the compiler doesn't discard certain return values
-// as something we don't need (see the comment with calloc below).
-template <typename Type>
-NOINLINE Type HideValueFromCompiler(volatile Type value) {
-#if defined(__GNUC__)
- // In a GCC compatible compiler (GCC or Clang), make this compiler barrier
- // more robust than merely using "volatile".
- __asm__ volatile ("" : "+r" (value));
-#endif // __GNUC__
- return value;
-}
-
-// TCmalloc, currently supported only by Linux/CrOS, supports malloc limits.
-// - NO_TCMALLOC (should be defined if compiled with use_allocator!="tcmalloc")
-// - ADDRESS_SANITIZER it has its own memory allocator
-#if defined(OS_LINUX) && !defined(NO_TCMALLOC) && !defined(ADDRESS_SANITIZER)
-#define MALLOC_OVERFLOW_TEST(function) function
-#else
-#define MALLOC_OVERFLOW_TEST(function) DISABLED_##function
-#endif
-
-// There are platforms where these tests are known to fail. We would like to
-// be able to easily check the status on the bots, but marking tests as
-// FAILS_ is too clunky.
-void OverflowTestsSoftExpectTrue(bool overflow_detected) {
- if (!overflow_detected) {
-#if defined(OS_LINUX) || defined(OS_ANDROID) || defined(OS_MACOSX)
- // Sadly, on Linux, Android, and OSX we don't have a good story yet. Don't
- // fail the test, but report.
- printf("Platform has overflow: %s\n",
- !overflow_detected ? "yes." : "no.");
-#else
- // Otherwise, fail the test. (Note: EXPECT are ok in subfunctions, ASSERT
- // aren't).
- EXPECT_TRUE(overflow_detected);
-#endif
- }
-}
-
-#if defined(OS_IOS) || defined(OS_FUCHSIA) || defined(ADDRESS_SANITIZER) || \
- defined(THREAD_SANITIZER) || defined(MEMORY_SANITIZER)
-#define MAYBE_NewOverflow DISABLED_NewOverflow
-#else
-#define MAYBE_NewOverflow NewOverflow
-#endif
-// Test array[TooBig][X] and array[X][TooBig] allocations for int overflows.
-// IOS doesn't honor nothrow, so disable the test there.
-// TODO(https://crbug.com/828229): Fuchsia SDK exports an incorrect new[] that
-// gets picked up in Debug/component builds, breaking this test.
-// Disabled under XSan because asan aborts when new returns nullptr,
-// https://bugs.chromium.org/p/chromium/issues/detail?id=690271#c15
-TEST(SecurityTest, MAYBE_NewOverflow) {
- const size_t kArraySize = 4096;
- // We want something "dynamic" here, so that the compiler doesn't
- // immediately reject crazy arrays.
- const size_t kDynamicArraySize = HideValueFromCompiler(kArraySize);
- const size_t kMaxSizeT = std::numeric_limits<size_t>::max();
- const size_t kArraySize2 = kMaxSizeT / kArraySize + 10;
- const size_t kDynamicArraySize2 = HideValueFromCompiler(kArraySize2);
- {
- std::unique_ptr<char[][kArraySize]> array_pointer(
- new (nothrow) char[kDynamicArraySize2][kArraySize]);
- // Prevent clang from optimizing away the whole test.
- char* volatile p = reinterpret_cast<char*>(array_pointer.get());
- OverflowTestsSoftExpectTrue(!p);
- }
- // On windows, the compiler prevents static array sizes of more than
- // 0x7fffffff (error C2148).
-#if defined(OS_WIN) && defined(ARCH_CPU_64_BITS)
- ALLOW_UNUSED_LOCAL(kDynamicArraySize);
-#else
- {
- std::unique_ptr<char[][kArraySize2]> array_pointer(
- new (nothrow) char[kDynamicArraySize][kArraySize2]);
- // Prevent clang from optimizing away the whole test.
- char* volatile p = reinterpret_cast<char*>(array_pointer.get());
- OverflowTestsSoftExpectTrue(!p);
- }
-#endif // !defined(OS_WIN) || !defined(ARCH_CPU_64_BITS)
-}
-
-#if defined(OS_LINUX) && defined(__x86_64__)
-// Check if ptr1 and ptr2 are separated by less than size chars.
-bool ArePointersToSameArea(void* ptr1, void* ptr2, size_t size) {
- ptrdiff_t ptr_diff = reinterpret_cast<char*>(std::max(ptr1, ptr2)) -
- reinterpret_cast<char*>(std::min(ptr1, ptr2));
- return static_cast<size_t>(ptr_diff) <= size;
-}
-
-// Check if TCMalloc uses an underlying random memory allocator.
-TEST(SecurityTest, MALLOC_OVERFLOW_TEST(RandomMemoryAllocations)) {
- size_t kPageSize = 4096; // We support x86_64 only.
- // Check that malloc() returns an address that is neither the kernel's
- // un-hinted mmap area, nor the current brk() area. The first malloc() may
- // not be at a random address because TCMalloc will first exhaust any memory
- // that it has allocated early on, before starting the sophisticated
- // allocators.
- void* default_mmap_heap_address =
- mmap(nullptr, kPageSize, PROT_READ | PROT_WRITE,
- MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
- ASSERT_NE(default_mmap_heap_address,
- static_cast<void*>(MAP_FAILED));
- ASSERT_EQ(munmap(default_mmap_heap_address, kPageSize), 0);
- void* brk_heap_address = sbrk(0);
- ASSERT_NE(brk_heap_address, reinterpret_cast<void*>(-1));
- ASSERT_TRUE(brk_heap_address != nullptr);
- // 1 MB should get us past what TCMalloc pre-allocated before initializing
- // the sophisticated allocators.
- size_t kAllocSize = 1<<20;
- std::unique_ptr<char, base::FreeDeleter> ptr(
- static_cast<char*>(malloc(kAllocSize)));
- ASSERT_TRUE(ptr != nullptr);
- // If two pointers are separated by less than 512MB, they are considered
- // to be in the same area.
- // Our random pointer could be anywhere within 0x3fffffffffff (46bits),
- // and we are checking that it's not withing 1GB (30 bits) from two
- // addresses (brk and mmap heap). We have roughly one chance out of
- // 2^15 to flake.
- const size_t kAreaRadius = 1<<29;
- bool in_default_mmap_heap = ArePointersToSameArea(
- ptr.get(), default_mmap_heap_address, kAreaRadius);
- EXPECT_FALSE(in_default_mmap_heap);
-
- bool in_default_brk_heap = ArePointersToSameArea(
- ptr.get(), brk_heap_address, kAreaRadius);
- EXPECT_FALSE(in_default_brk_heap);
-
- // In the implementation, we always mask our random addresses with
- // kRandomMask, so we use it as an additional detection mechanism.
- const uintptr_t kRandomMask = 0x3fffffffffffULL;
- bool impossible_random_address =
- reinterpret_cast<uintptr_t>(ptr.get()) & ~kRandomMask;
- EXPECT_FALSE(impossible_random_address);
-}
-
-#endif // defined(OS_LINUX) && defined(__x86_64__)
-
-} // namespace
diff --git a/base/sequence_checker_unittest.cc b/base/sequence_checker_unittest.cc
deleted file mode 100644
index 8d44f3e..0000000
--- a/base/sequence_checker_unittest.cc
+++ /dev/null
@@ -1,181 +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/sequence_checker.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/callback_forward.h"
-#include "base/macros.h"
-#include "base/sequence_token.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// Runs a callback on another thread.
-class RunCallbackThread : public SimpleThread {
- public:
- explicit RunCallbackThread(const Closure& callback)
- : SimpleThread("RunCallbackThread"), callback_(callback) {
- Start();
- Join();
- }
-
- private:
- // SimpleThread:
- void Run() override { callback_.Run(); }
-
- const Closure callback_;
-
- DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
-};
-
-void ExpectCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
- ASSERT_TRUE(sequence_checker);
-
- // This should bind |sequence_checker| to the current sequence if it wasn't
- // already bound to a sequence.
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
-
- // Since |sequence_checker| is now bound to the current sequence, another call
- // to CalledOnValidSequence() should return true.
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
-}
-
-void ExpectCalledOnValidSequenceWithSequenceToken(
- SequenceCheckerImpl* sequence_checker,
- SequenceToken sequence_token) {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(sequence_token);
- ExpectCalledOnValidSequence(sequence_checker);
-}
-
-void ExpectNotCalledOnValidSequence(SequenceCheckerImpl* sequence_checker) {
- ASSERT_TRUE(sequence_checker);
- EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
-}
-
-} // namespace
-
-TEST(SequenceCheckerTest, CallsAllowedOnSameThreadNoSequenceToken) {
- SequenceCheckerImpl sequence_checker;
- EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
-}
-
-TEST(SequenceCheckerTest, CallsAllowedOnSameThreadSameSequenceToken) {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- SequenceCheckerImpl sequence_checker;
- EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
-}
-
-TEST(SequenceCheckerTest, CallsDisallowedOnDifferentThreadsNoSequenceToken) {
- SequenceCheckerImpl sequence_checker;
- RunCallbackThread thread(
- Bind(&ExpectNotCalledOnValidSequence, Unretained(&sequence_checker)));
-}
-
-TEST(SequenceCheckerTest, CallsAllowedOnDifferentThreadsSameSequenceToken) {
- const SequenceToken sequence_token(SequenceToken::Create());
-
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(sequence_token);
- SequenceCheckerImpl sequence_checker;
- EXPECT_TRUE(sequence_checker.CalledOnValidSequence());
-
- RunCallbackThread thread(Bind(&ExpectCalledOnValidSequenceWithSequenceToken,
- Unretained(&sequence_checker), sequence_token));
-}
-
-TEST(SequenceCheckerTest, CallsDisallowedOnSameThreadDifferentSequenceToken) {
- std::unique_ptr<SequenceCheckerImpl> sequence_checker;
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- sequence_checker.reset(new SequenceCheckerImpl);
- }
-
- {
- // Different SequenceToken.
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
- }
-
- // No SequenceToken.
- EXPECT_FALSE(sequence_checker->CalledOnValidSequence());
-}
-
-TEST(SequenceCheckerTest, DetachFromSequence) {
- std::unique_ptr<SequenceCheckerImpl> sequence_checker;
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- sequence_checker.reset(new SequenceCheckerImpl);
- }
-
- sequence_checker->DetachFromSequence();
-
- {
- // Verify that CalledOnValidSequence() returns true when called with
- // a different sequence token after a call to DetachFromSequence().
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
- }
-}
-
-TEST(SequenceCheckerTest, DetachFromSequenceNoSequenceToken) {
- SequenceCheckerImpl sequence_checker;
- sequence_checker.DetachFromSequence();
-
- // Verify that CalledOnValidSequence() returns true when called on a
- // different thread after a call to DetachFromSequence().
- RunCallbackThread thread(
- Bind(&ExpectCalledOnValidSequence, Unretained(&sequence_checker)));
-
- EXPECT_FALSE(sequence_checker.CalledOnValidSequence());
-}
-
-TEST(SequenceCheckerMacroTest, Macros) {
- auto scope = std::make_unique<ScopedSetSequenceTokenForCurrentThread>(
- SequenceToken::Create());
- SEQUENCE_CHECKER(my_sequence_checker);
-
- // Don't expect a DCHECK death when a SequenceChecker is used on the right
- // sequence.
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
-
- scope.reset();
-
-#if DCHECK_IS_ON()
- // Expect DCHECK death when used on a different sequence.
- EXPECT_DCHECK_DEATH({
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
- });
-#else
- // Happily no-ops on non-dcheck builds.
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
-#endif
-
- DETACH_FROM_SEQUENCE(my_sequence_checker);
-
- // Don't expect a DCHECK death when a SequenceChecker is used for the first
- // time after having been detached.
- DCHECK_CALLED_ON_VALID_SEQUENCE(my_sequence_checker) << "Error message.";
-}
-
-} // namespace base
diff --git a/base/sequence_token_unittest.cc b/base/sequence_token_unittest.cc
deleted file mode 100644
index 2ed6878..0000000
--- a/base/sequence_token_unittest.cc
+++ /dev/null
@@ -1,133 +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/sequence_token.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(SequenceTokenTest, IsValid) {
- EXPECT_FALSE(SequenceToken().IsValid());
- EXPECT_TRUE(SequenceToken::Create().IsValid());
-}
-
-TEST(SequenceTokenTest, OperatorEquals) {
- const SequenceToken invalid_a;
- const SequenceToken invalid_b;
- const SequenceToken valid_a = SequenceToken::Create();
- const SequenceToken valid_b = SequenceToken::Create();
-
- EXPECT_FALSE(invalid_a == invalid_a);
- EXPECT_FALSE(invalid_a == invalid_b);
- EXPECT_FALSE(invalid_a == valid_a);
- EXPECT_FALSE(invalid_a == valid_b);
-
- EXPECT_FALSE(valid_a == invalid_a);
- EXPECT_FALSE(valid_a == invalid_b);
- EXPECT_EQ(valid_a, valid_a);
- EXPECT_FALSE(valid_a == valid_b);
-}
-
-TEST(SequenceTokenTest, OperatorNotEquals) {
- const SequenceToken invalid_a;
- const SequenceToken invalid_b;
- const SequenceToken valid_a = SequenceToken::Create();
- const SequenceToken valid_b = SequenceToken::Create();
-
- EXPECT_NE(invalid_a, invalid_a);
- EXPECT_NE(invalid_a, invalid_b);
- EXPECT_NE(invalid_a, valid_a);
- EXPECT_NE(invalid_a, valid_b);
-
- EXPECT_NE(valid_a, invalid_a);
- EXPECT_NE(valid_a, invalid_b);
- EXPECT_FALSE(valid_a != valid_a);
- EXPECT_NE(valid_a, valid_b);
-}
-
-TEST(SequenceTokenTest, GetForCurrentThread) {
- const SequenceToken token = SequenceToken::Create();
-
- EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(token);
- EXPECT_TRUE(SequenceToken::GetForCurrentThread().IsValid());
- EXPECT_EQ(token, SequenceToken::GetForCurrentThread());
- }
-
- EXPECT_FALSE(SequenceToken::GetForCurrentThread().IsValid());
-}
-
-TEST(SequenceTokenTest, ToInternalValue) {
- const SequenceToken token1 = SequenceToken::Create();
- const SequenceToken token2 = SequenceToken::Create();
-
- // Confirm that internal values are unique.
- EXPECT_NE(token1.ToInternalValue(), token2.ToInternalValue());
-}
-
-// Expect a default-constructed TaskToken to be invalid and not equal to
-// another invalid TaskToken.
-TEST(TaskTokenTest, InvalidDefaultConstructed) {
- EXPECT_FALSE(TaskToken().IsValid());
- EXPECT_NE(TaskToken(), TaskToken());
-}
-
-// Expect a TaskToken returned by TaskToken::GetForCurrentThread() outside the
-// scope of a ScopedSetSequenceTokenForCurrentThread to be invalid.
-TEST(TaskTokenTest, InvalidOutsideScope) {
- EXPECT_FALSE(TaskToken::GetForCurrentThread().IsValid());
-}
-
-// Expect an invalid TaskToken not to be equal with a valid TaskToken.
-TEST(TaskTokenTest, ValidNotEqualsInvalid) {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- TaskToken valid = TaskToken::GetForCurrentThread();
- TaskToken invalid;
- EXPECT_NE(valid, invalid);
-}
-
-// Expect TaskTokens returned by TaskToken::GetForCurrentThread() in the scope
-// of the same ScopedSetSequenceTokenForCurrentThread instance to be
-// valid and equal with each other.
-TEST(TaskTokenTest, EqualInSameScope) {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
-
- const TaskToken token_a = TaskToken::GetForCurrentThread();
- const TaskToken token_b = TaskToken::GetForCurrentThread();
-
- EXPECT_TRUE(token_a.IsValid());
- EXPECT_TRUE(token_b.IsValid());
- EXPECT_EQ(token_a, token_b);
-}
-
-// Expect TaskTokens returned by TaskToken::GetForCurrentThread() in the scope
-// of different ScopedSetSequenceTokenForCurrentThread instances to be
-// valid but not equal to each other.
-TEST(TaskTokenTest, NotEqualInDifferentScopes) {
- TaskToken token_a;
- TaskToken token_b;
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- token_a = TaskToken::GetForCurrentThread();
- }
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- token_b = TaskToken::GetForCurrentThread();
- }
-
- EXPECT_TRUE(token_a.IsValid());
- EXPECT_TRUE(token_b.IsValid());
- EXPECT_NE(token_a, token_b);
-}
-
-} // namespace base
diff --git a/base/sequenced_task_runner_unittest.cc b/base/sequenced_task_runner_unittest.cc
deleted file mode 100644
index 4dcc7e5..0000000
--- 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/sha1_unittest.cc b/base/sha1_unittest.cc
deleted file mode 100644
index ea9cf63..0000000
--- a/base/sha1_unittest.cc
+++ /dev/null
@@ -1,109 +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/sha1.h"
-
-#include <stddef.h>
-
-#include <string>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-TEST(SHA1Test, Test1) {
- // Example A.1 from FIPS 180-2: one-block message.
- std::string input = "abc";
-
- int expected[] = { 0xa9, 0x99, 0x3e, 0x36,
- 0x47, 0x06, 0x81, 0x6a,
- 0xba, 0x3e, 0x25, 0x71,
- 0x78, 0x50, 0xc2, 0x6c,
- 0x9c, 0xd0, 0xd8, 0x9d };
-
- std::string output = base::SHA1HashString(input);
- for (size_t i = 0; i < base::kSHA1Length; i++)
- EXPECT_EQ(expected[i], output[i] & 0xFF);
-}
-
-TEST(SHA1Test, Test2) {
- // Example A.2 from FIPS 180-2: multi-block message.
- std::string input =
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
-
- int expected[] = { 0x84, 0x98, 0x3e, 0x44,
- 0x1c, 0x3b, 0xd2, 0x6e,
- 0xba, 0xae, 0x4a, 0xa1,
- 0xf9, 0x51, 0x29, 0xe5,
- 0xe5, 0x46, 0x70, 0xf1 };
-
- std::string output = base::SHA1HashString(input);
- for (size_t i = 0; i < base::kSHA1Length; i++)
- EXPECT_EQ(expected[i], output[i] & 0xFF);
-}
-
-TEST(SHA1Test, Test3) {
- // Example A.3 from FIPS 180-2: long message.
- std::string input(1000000, 'a');
-
- int expected[] = { 0x34, 0xaa, 0x97, 0x3c,
- 0xd4, 0xc4, 0xda, 0xa4,
- 0xf6, 0x1e, 0xeb, 0x2b,
- 0xdb, 0xad, 0x27, 0x31,
- 0x65, 0x34, 0x01, 0x6f };
-
- std::string output = base::SHA1HashString(input);
- for (size_t i = 0; i < base::kSHA1Length; i++)
- EXPECT_EQ(expected[i], output[i] & 0xFF);
-}
-
-TEST(SHA1Test, Test1Bytes) {
- // Example A.1 from FIPS 180-2: one-block message.
- std::string input = "abc";
- unsigned char output[base::kSHA1Length];
-
- unsigned char expected[] = { 0xa9, 0x99, 0x3e, 0x36,
- 0x47, 0x06, 0x81, 0x6a,
- 0xba, 0x3e, 0x25, 0x71,
- 0x78, 0x50, 0xc2, 0x6c,
- 0x9c, 0xd0, 0xd8, 0x9d };
-
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(input.c_str()),
- input.length(), output);
- for (size_t i = 0; i < base::kSHA1Length; i++)
- EXPECT_EQ(expected[i], output[i]);
-}
-
-TEST(SHA1Test, Test2Bytes) {
- // Example A.2 from FIPS 180-2: multi-block message.
- std::string input =
- "abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq";
- unsigned char output[base::kSHA1Length];
-
- unsigned char expected[] = { 0x84, 0x98, 0x3e, 0x44,
- 0x1c, 0x3b, 0xd2, 0x6e,
- 0xba, 0xae, 0x4a, 0xa1,
- 0xf9, 0x51, 0x29, 0xe5,
- 0xe5, 0x46, 0x70, 0xf1 };
-
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(input.c_str()),
- input.length(), output);
- for (size_t i = 0; i < base::kSHA1Length; i++)
- EXPECT_EQ(expected[i], output[i]);
-}
-
-TEST(SHA1Test, Test3Bytes) {
- // Example A.3 from FIPS 180-2: long message.
- std::string input(1000000, 'a');
- unsigned char output[base::kSHA1Length];
-
- unsigned char expected[] = { 0x34, 0xaa, 0x97, 0x3c,
- 0xd4, 0xc4, 0xda, 0xa4,
- 0xf6, 0x1e, 0xeb, 0x2b,
- 0xdb, 0xad, 0x27, 0x31,
- 0x65, 0x34, 0x01, 0x6f };
-
- base::SHA1HashBytes(reinterpret_cast<const unsigned char*>(input.c_str()),
- input.length(), output);
- for (size_t i = 0; i < base::kSHA1Length; i++)
- EXPECT_EQ(expected[i], output[i]);
-}
diff --git a/base/stl_util_unittest.cc b/base/stl_util_unittest.cc
deleted file mode 100644
index f13f881..0000000
--- a/base/stl_util_unittest.cc
+++ /dev/null
@@ -1,612 +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.
-
-#include "base/stl_util.h"
-
-#include <array>
-#include <deque>
-#include <forward_list>
-#include <functional>
-#include <initializer_list>
-#include <iterator>
-#include <list>
-#include <map>
-#include <queue>
-#include <set>
-#include <stack>
-#include <string>
-#include <type_traits>
-#include <unordered_map>
-#include <unordered_set>
-#include <vector>
-
-#include "base/containers/queue.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-// Used as test case to ensure the various base::STLXxx functions don't require
-// more than operators "<" and "==" on values stored in containers.
-class ComparableValue {
- public:
- explicit ComparableValue(int value) : value_(value) {}
-
- bool operator==(const ComparableValue& rhs) const {
- return value_ == rhs.value_;
- }
-
- bool operator<(const ComparableValue& rhs) const {
- return value_ < rhs.value_;
- }
-
- private:
- int value_;
-};
-
-template <typename Container>
-void RunEraseTest() {
- const std::pair<Container, Container> test_data[] = {
- {Container(), Container()}, {{1, 2, 3}, {1, 3}}, {{1, 2, 3, 2}, {1, 3}}};
-
- for (auto test_case : test_data) {
- base::Erase(test_case.first, 2);
- EXPECT_EQ(test_case.second, test_case.first);
- }
-}
-
-// This test is written for containers of std::pair<int, int> to support maps.
-template <typename Container>
-void RunEraseIfTest() {
- struct {
- Container input;
- Container erase_even;
- Container erase_odd;
- } test_data[] = {
- {Container(), Container(), Container()},
- {{{1, 1}, {2, 2}, {3, 3}}, {{1, 1}, {3, 3}}, {{2, 2}}},
- {{{1, 1}, {2, 2}, {3, 3}, {4, 4}}, {{1, 1}, {3, 3}}, {{2, 2}, {4, 4}}},
- };
-
- for (auto test_case : test_data) {
- base::EraseIf(test_case.input, [](const std::pair<int, int>& elem) {
- return !(elem.first & 1);
- });
- EXPECT_EQ(test_case.erase_even, test_case.input);
- }
-
- for (auto test_case : test_data) {
- base::EraseIf(test_case.input, [](const std::pair<int, int>& elem) {
- return elem.first & 1;
- });
- EXPECT_EQ(test_case.erase_odd, test_case.input);
- }
-}
-
-struct CustomIntHash {
- size_t operator()(int elem) const { return std::hash<int>()(elem) + 1; }
-};
-
-struct HashByFirst {
- size_t operator()(const std::pair<int, int>& elem) const {
- return std::hash<int>()(elem.first);
- }
-};
-
-} // namespace
-
-namespace base {
-namespace {
-
-TEST(STLUtilTest, Size) {
- {
- std::vector<int> vector = {1, 2, 3, 4, 5};
- static_assert(
- std::is_same<decltype(base::size(vector)),
- decltype(vector.size())>::value,
- "base::size(vector) should have the same type as vector.size()");
- EXPECT_EQ(vector.size(), base::size(vector));
- }
-
- {
- std::string empty_str;
- static_assert(
- std::is_same<decltype(base::size(empty_str)),
- decltype(empty_str.size())>::value,
- "base::size(empty_str) should have the same type as empty_str.size()");
- EXPECT_EQ(0u, base::size(empty_str));
- }
-
- {
- std::array<int, 4> array = {{1, 2, 3, 4}};
- static_assert(
- std::is_same<decltype(base::size(array)),
- decltype(array.size())>::value,
- "base::size(array) should have the same type as array.size()");
- static_assert(base::size(array) == array.size(),
- "base::size(array) should be equal to array.size()");
- }
-
- {
- int array[] = {1, 2, 3};
- static_assert(std::is_same<size_t, decltype(base::size(array))>::value,
- "base::size(array) should be of type size_t");
- static_assert(3u == base::size(array), "base::size(array) should be 3");
- }
-}
-
-TEST(STLUtilTest, Empty) {
- {
- std::vector<int> vector;
- static_assert(
- std::is_same<decltype(base::empty(vector)),
- decltype(vector.empty())>::value,
- "base::empty(vector) should have the same type as vector.empty()");
- EXPECT_EQ(vector.empty(), base::empty(vector));
- }
-
- {
- std::array<int, 4> array = {{1, 2, 3, 4}};
- static_assert(
- std::is_same<decltype(base::empty(array)),
- decltype(array.empty())>::value,
- "base::empty(array) should have the same type as array.empty()");
- static_assert(base::empty(array) == array.empty(),
- "base::empty(array) should be equal to array.empty()");
- }
-
- {
- int array[] = {1, 2, 3};
- static_assert(std::is_same<bool, decltype(base::empty(array))>::value,
- "base::empty(array) should be of type bool");
- static_assert(!base::empty(array), "base::empty(array) should be false");
- }
-
- {
- constexpr std::initializer_list<int> il;
- static_assert(std::is_same<bool, decltype(base::empty(il))>::value,
- "base::empty(il) should be of type bool");
- static_assert(base::empty(il), "base::empty(il) should be true");
- }
-}
-
-TEST(STLUtilTest, Data) {
- {
- std::vector<int> vector = {1, 2, 3, 4, 5};
- static_assert(
- std::is_same<decltype(base::data(vector)),
- decltype(vector.data())>::value,
- "base::data(vector) should have the same type as vector.data()");
- EXPECT_EQ(vector.data(), base::data(vector));
- }
-
- {
- const std::string cstr = "const string";
- static_assert(
- std::is_same<decltype(base::data(cstr)), decltype(cstr.data())>::value,
- "base::data(cstr) should have the same type as cstr.data()");
-
- EXPECT_EQ(cstr.data(), base::data(cstr));
- }
-
- {
- std::string str = "mutable string";
- static_assert(std::is_same<decltype(base::data(str)), char*>::value,
- "base::data(str) should be of type char*");
- EXPECT_EQ(str.data(), base::data(str));
- }
-
- {
- std::string empty_str;
- static_assert(std::is_same<decltype(base::data(empty_str)), char*>::value,
- "base::data(empty_str) should be of type char*");
- EXPECT_EQ(empty_str.data(), base::data(empty_str));
- }
-
- {
- std::array<int, 4> array = {{1, 2, 3, 4}};
- static_assert(
- std::is_same<decltype(base::data(array)),
- decltype(array.data())>::value,
- "base::data(array) should have the same type as array.data()");
- // std::array::data() is not constexpr prior to C++17, hence the runtime
- // check.
- EXPECT_EQ(array.data(), base::data(array));
- }
-
- {
- constexpr int array[] = {1, 2, 3};
- static_assert(std::is_same<const int*, decltype(base::data(array))>::value,
- "base::data(array) should be of type const int*");
- static_assert(array == base::data(array),
- "base::data(array) should be array");
- }
-
- {
- constexpr std::initializer_list<int> il;
- static_assert(
- std::is_same<decltype(il.begin()), decltype(base::data(il))>::value,
- "base::data(il) should have the same type as il.begin()");
- static_assert(il.begin() == base::data(il),
- "base::data(il) should be equal to il.begin()");
- }
-}
-
-TEST(STLUtilTest, GetUnderlyingContainer) {
- {
- std::queue<int> queue({1, 2, 3, 4, 5});
- static_assert(std::is_same<decltype(GetUnderlyingContainer(queue)),
- const std::deque<int>&>::value,
- "GetUnderlyingContainer(queue) should be of type deque");
- EXPECT_THAT(GetUnderlyingContainer(queue),
- testing::ElementsAre(1, 2, 3, 4, 5));
- }
-
- {
- std::queue<int> queue;
- EXPECT_THAT(GetUnderlyingContainer(queue), testing::ElementsAre());
- }
-
- {
- base::queue<int> queue({1, 2, 3, 4, 5});
- static_assert(
- std::is_same<decltype(GetUnderlyingContainer(queue)),
- const base::circular_deque<int>&>::value,
- "GetUnderlyingContainer(queue) should be of type circular_deque");
- EXPECT_THAT(GetUnderlyingContainer(queue),
- testing::ElementsAre(1, 2, 3, 4, 5));
- }
-
- {
- std::vector<int> values = {1, 2, 3, 4, 5};
- std::priority_queue<int> queue(values.begin(), values.end());
- static_assert(std::is_same<decltype(GetUnderlyingContainer(queue)),
- const std::vector<int>&>::value,
- "GetUnderlyingContainer(queue) should be of type vector");
- EXPECT_THAT(GetUnderlyingContainer(queue),
- testing::UnorderedElementsAre(1, 2, 3, 4, 5));
- }
-
- {
- std::stack<int> stack({1, 2, 3, 4, 5});
- static_assert(std::is_same<decltype(GetUnderlyingContainer(stack)),
- const std::deque<int>&>::value,
- "GetUnderlyingContainer(stack) should be of type deque");
- EXPECT_THAT(GetUnderlyingContainer(stack),
- testing::ElementsAre(1, 2, 3, 4, 5));
- }
-}
-
-TEST(STLUtilTest, STLIsSorted) {
- {
- std::set<int> set;
- set.insert(24);
- set.insert(1);
- set.insert(12);
- EXPECT_TRUE(STLIsSorted(set));
- }
-
- {
- std::set<ComparableValue> set;
- set.insert(ComparableValue(24));
- set.insert(ComparableValue(1));
- set.insert(ComparableValue(12));
- EXPECT_TRUE(STLIsSorted(set));
- }
-
- {
- std::vector<int> vector;
- vector.push_back(1);
- vector.push_back(1);
- vector.push_back(4);
- vector.push_back(64);
- vector.push_back(12432);
- EXPECT_TRUE(STLIsSorted(vector));
- vector.back() = 1;
- EXPECT_FALSE(STLIsSorted(vector));
- }
-}
-
-TEST(STLUtilTest, STLSetDifference) {
- std::set<int> a1;
- a1.insert(1);
- a1.insert(2);
- a1.insert(3);
- a1.insert(4);
-
- std::set<int> a2;
- a2.insert(3);
- a2.insert(4);
- a2.insert(5);
- a2.insert(6);
- a2.insert(7);
-
- {
- std::set<int> difference;
- difference.insert(1);
- difference.insert(2);
- EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a1, a2));
- }
-
- {
- std::set<int> difference;
- difference.insert(5);
- difference.insert(6);
- difference.insert(7);
- EXPECT_EQ(difference, STLSetDifference<std::set<int> >(a2, a1));
- }
-
- {
- std::vector<int> difference;
- difference.push_back(1);
- difference.push_back(2);
- EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a1, a2));
- }
-
- {
- std::vector<int> difference;
- difference.push_back(5);
- difference.push_back(6);
- difference.push_back(7);
- EXPECT_EQ(difference, STLSetDifference<std::vector<int> >(a2, a1));
- }
-}
-
-TEST(STLUtilTest, STLSetUnion) {
- std::set<int> a1;
- a1.insert(1);
- a1.insert(2);
- a1.insert(3);
- a1.insert(4);
-
- std::set<int> a2;
- a2.insert(3);
- a2.insert(4);
- a2.insert(5);
- a2.insert(6);
- a2.insert(7);
-
- {
- std::set<int> result;
- result.insert(1);
- result.insert(2);
- result.insert(3);
- result.insert(4);
- result.insert(5);
- result.insert(6);
- result.insert(7);
- EXPECT_EQ(result, STLSetUnion<std::set<int> >(a1, a2));
- }
-
- {
- std::set<int> result;
- result.insert(1);
- result.insert(2);
- result.insert(3);
- result.insert(4);
- result.insert(5);
- result.insert(6);
- result.insert(7);
- EXPECT_EQ(result, STLSetUnion<std::set<int> >(a2, a1));
- }
-
- {
- std::vector<int> result;
- result.push_back(1);
- result.push_back(2);
- result.push_back(3);
- result.push_back(4);
- result.push_back(5);
- result.push_back(6);
- result.push_back(7);
- EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a1, a2));
- }
-
- {
- std::vector<int> result;
- result.push_back(1);
- result.push_back(2);
- result.push_back(3);
- result.push_back(4);
- result.push_back(5);
- result.push_back(6);
- result.push_back(7);
- EXPECT_EQ(result, STLSetUnion<std::vector<int> >(a2, a1));
- }
-}
-
-TEST(STLUtilTest, STLSetIntersection) {
- std::set<int> a1;
- a1.insert(1);
- a1.insert(2);
- a1.insert(3);
- a1.insert(4);
-
- std::set<int> a2;
- a2.insert(3);
- a2.insert(4);
- a2.insert(5);
- a2.insert(6);
- a2.insert(7);
-
- {
- std::set<int> result;
- result.insert(3);
- result.insert(4);
- EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a1, a2));
- }
-
- {
- std::set<int> result;
- result.insert(3);
- result.insert(4);
- EXPECT_EQ(result, STLSetIntersection<std::set<int> >(a2, a1));
- }
-
- {
- std::vector<int> result;
- result.push_back(3);
- result.push_back(4);
- EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a1, a2));
- }
-
- {
- std::vector<int> result;
- result.push_back(3);
- result.push_back(4);
- EXPECT_EQ(result, STLSetIntersection<std::vector<int> >(a2, a1));
- }
-}
-
-TEST(STLUtilTest, STLIncludes) {
- std::set<int> a1;
- a1.insert(1);
- a1.insert(2);
- a1.insert(3);
- a1.insert(4);
-
- std::set<int> a2;
- a2.insert(3);
- a2.insert(4);
-
- std::set<int> a3;
- a3.insert(3);
- a3.insert(4);
- a3.insert(5);
-
- EXPECT_TRUE(STLIncludes<std::set<int> >(a1, a2));
- EXPECT_FALSE(STLIncludes<std::set<int> >(a1, a3));
- EXPECT_FALSE(STLIncludes<std::set<int> >(a2, a1));
- EXPECT_FALSE(STLIncludes<std::set<int> >(a2, a3));
- EXPECT_FALSE(STLIncludes<std::set<int> >(a3, a1));
- EXPECT_TRUE(STLIncludes<std::set<int> >(a3, a2));
-}
-
-TEST(Erase, String) {
- const std::pair<std::string, std::string> test_data[] = {
- {"", ""}, {"abc", "bc"}, {"abca", "bc"},
- };
-
- for (auto test_case : test_data) {
- Erase(test_case.first, 'a');
- EXPECT_EQ(test_case.second, test_case.first);
- }
-
- for (auto test_case : test_data) {
- EraseIf(test_case.first, [](char elem) { return elem < 'b'; });
- EXPECT_EQ(test_case.second, test_case.first);
- }
-}
-
-TEST(Erase, String16) {
- std::pair<base::string16, base::string16> test_data[] = {
- {base::string16(), base::string16()},
- {UTF8ToUTF16("abc"), UTF8ToUTF16("bc")},
- {UTF8ToUTF16("abca"), UTF8ToUTF16("bc")},
- };
-
- const base::string16 letters = UTF8ToUTF16("ab");
- for (auto test_case : test_data) {
- Erase(test_case.first, letters[0]);
- EXPECT_EQ(test_case.second, test_case.first);
- }
-
- for (auto test_case : test_data) {
- EraseIf(test_case.first, [&](short elem) { return elem < letters[1]; });
- EXPECT_EQ(test_case.second, test_case.first);
- }
-}
-
-TEST(Erase, Deque) {
- RunEraseTest<std::deque<int>>();
- RunEraseIfTest<std::deque<std::pair<int, int>>>();
-}
-
-TEST(Erase, Vector) {
- RunEraseTest<std::vector<int>>();
- RunEraseIfTest<std::vector<std::pair<int, int>>>();
-}
-
-TEST(Erase, ForwardList) {
- RunEraseTest<std::forward_list<int>>();
- RunEraseIfTest<std::forward_list<std::pair<int, int>>>();
-}
-
-TEST(Erase, List) {
- RunEraseTest<std::list<int>>();
- RunEraseIfTest<std::list<std::pair<int, int>>>();
-}
-
-TEST(Erase, Map) {
- RunEraseIfTest<std::map<int, int>>();
- RunEraseIfTest<std::map<int, int, std::greater<int>>>();
-}
-
-TEST(Erase, Multimap) {
- RunEraseIfTest<std::multimap<int, int>>();
- RunEraseIfTest<std::multimap<int, int, std::greater<int>>>();
-}
-
-TEST(Erase, Set) {
- RunEraseIfTest<std::set<std::pair<int, int>>>();
- RunEraseIfTest<
- std::set<std::pair<int, int>, std::greater<std::pair<int, int>>>>();
-}
-
-TEST(Erase, Multiset) {
- RunEraseIfTest<std::multiset<std::pair<int, int>>>();
- RunEraseIfTest<
- std::multiset<std::pair<int, int>, std::greater<std::pair<int, int>>>>();
-}
-
-TEST(Erase, UnorderedMap) {
- RunEraseIfTest<std::unordered_map<int, int>>();
- RunEraseIfTest<std::unordered_map<int, int, CustomIntHash>>();
-}
-
-TEST(Erase, UnorderedMultimap) {
- RunEraseIfTest<std::unordered_multimap<int, int>>();
- RunEraseIfTest<std::unordered_multimap<int, int, CustomIntHash>>();
-}
-
-TEST(Erase, UnorderedSet) {
- RunEraseIfTest<std::unordered_set<std::pair<int, int>, HashByFirst>>();
-}
-
-TEST(Erase, UnorderedMultiset) {
- RunEraseIfTest<std::unordered_multiset<std::pair<int, int>, HashByFirst>>();
-}
-
-TEST(Erase, IsNotIn) {
- // Should keep both '2' but only one '4', like std::set_intersection.
- std::vector<int> lhs = {0, 2, 2, 4, 4, 4, 6, 8, 10};
- std::vector<int> rhs = {1, 2, 2, 4, 5, 6, 7};
- std::vector<int> expected = {2, 2, 4, 6};
- EraseIf(lhs, IsNotIn<std::vector<int>>(rhs));
- EXPECT_EQ(expected, lhs);
-}
-
-TEST(ContainsValue, OrdinaryArrays) {
- const char allowed_chars[] = {'a', 'b', 'c', 'd'};
- EXPECT_TRUE(ContainsValue(allowed_chars, 'a'));
- EXPECT_FALSE(ContainsValue(allowed_chars, 'z'));
- EXPECT_FALSE(ContainsValue(allowed_chars, 0));
-
- const char allowed_chars_including_nul[] = "abcd";
- EXPECT_TRUE(ContainsValue(allowed_chars_including_nul, 0));
-}
-
-TEST(STLUtilTest, OptionalOrNullptr) {
- Optional<float> optional;
- EXPECT_EQ(nullptr, base::OptionalOrNullptr(optional));
-
- optional = 0.1f;
- EXPECT_EQ(&optional.value(), base::OptionalOrNullptr(optional));
- EXPECT_NE(nullptr, base::OptionalOrNullptr(optional));
-}
-
-} // namespace
-} // namespace base
diff --git a/base/strings/char_traits_unittest.cc b/base/strings/char_traits_unittest.cc
deleted file mode 100644
index 31c421b..0000000
--- a/base/strings/char_traits_unittest.cc
+++ /dev/null
@@ -1,32 +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/strings/char_traits.h"
-#include "base/strings/string16.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(CharTraitsTest, CharCompare) {
- static_assert(CharTraits<char>::compare("abc", "def", 3) == -1, "");
- static_assert(CharTraits<char>::compare("def", "def", 3) == 0, "");
- static_assert(CharTraits<char>::compare("ghi", "def", 3) == 1, "");
-}
-
-TEST(CharTraitsTest, CharLength) {
- static_assert(CharTraits<char>::length("") == 0, "");
- static_assert(CharTraits<char>::length("abc") == 3, "");
-}
-
-TEST(CharTraitsTest, Char16TCompare) {
- static_assert(CharTraits<char16_t>::compare(u"abc", u"def", 3) == -1, "");
- static_assert(CharTraits<char16_t>::compare(u"def", u"def", 3) == 0, "");
- static_assert(CharTraits<char16_t>::compare(u"ghi", u"def", 3) == 1, "");
-}
-
-TEST(CharTraitsTest, Char16TLength) {
- static_assert(CharTraits<char16_t>::length(u"abc") == 3, "");
-}
-
-} // namespace base
diff --git a/base/strings/nullable_string16_unittest.cc b/base/strings/nullable_string16_unittest.cc
deleted file mode 100644
index f02fdce..0000000
--- a/base/strings/nullable_string16_unittest.cc
+++ /dev/null
@@ -1,35 +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/nullable_string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(NullableString16Test, DefaultConstructor) {
- NullableString16 s;
- EXPECT_TRUE(s.is_null());
- EXPECT_EQ(string16(), s.string());
-}
-
-TEST(NullableString16Test, Equals) {
- NullableString16 a(ASCIIToUTF16("hello"), false);
- NullableString16 b(ASCIIToUTF16("hello"), false);
- EXPECT_EQ(a, b);
-}
-
-TEST(NullableString16Test, NotEquals) {
- NullableString16 a(ASCIIToUTF16("hello"), false);
- NullableString16 b(ASCIIToUTF16("world"), false);
- EXPECT_NE(a, b);
-}
-
-TEST(NullableString16Test, NotEqualsNull) {
- NullableString16 a(ASCIIToUTF16("hello"), false);
- NullableString16 b;
- EXPECT_NE(a, b);
-}
-
-} // namespace base
diff --git a/base/strings/pattern_unittest.cc b/base/strings/pattern_unittest.cc
deleted file mode 100644
index 8ec5495..0000000
--- a/base/strings/pattern_unittest.cc
+++ /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.
-
-#include "base/strings/pattern.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(StringUtilTest, MatchPatternTest) {
- EXPECT_TRUE(MatchPattern("www.google.com", "*.com"));
- EXPECT_TRUE(MatchPattern("www.google.com", "*"));
- EXPECT_FALSE(MatchPattern("www.google.com", "www*.g*.org"));
- EXPECT_TRUE(MatchPattern("Hello", "H?l?o"));
- EXPECT_FALSE(MatchPattern("www.google.com", "http://*)"));
- EXPECT_FALSE(MatchPattern("www.msn.com", "*.COM"));
- EXPECT_TRUE(MatchPattern("Hello*1234", "He??o\\*1*"));
- EXPECT_FALSE(MatchPattern("", "*.*"));
- EXPECT_TRUE(MatchPattern("", "*"));
- EXPECT_TRUE(MatchPattern("", "?"));
- EXPECT_TRUE(MatchPattern("", ""));
- EXPECT_FALSE(MatchPattern("Hello", ""));
- EXPECT_TRUE(MatchPattern("Hello*", "Hello*"));
- EXPECT_TRUE(MatchPattern("abcd", "*???"));
- EXPECT_FALSE(MatchPattern("abcd", "???"));
- EXPECT_TRUE(MatchPattern("abcb", "a*b"));
- EXPECT_FALSE(MatchPattern("abcb", "a?b"));
-
- // Test UTF8 matching.
- EXPECT_TRUE(MatchPattern("heart: \xe2\x99\xa0", "*\xe2\x99\xa0"));
- EXPECT_TRUE(MatchPattern("heart: \xe2\x99\xa0.", "heart: ?."));
- EXPECT_TRUE(MatchPattern("hearts: \xe2\x99\xa0\xe2\x99\xa0", "*"));
- // Invalid sequences should be handled as a single invalid character.
- EXPECT_TRUE(MatchPattern("invalid: \xef\xbf\xbe", "invalid: ?"));
- // If the pattern has invalid characters, it shouldn't match anything.
- EXPECT_FALSE(MatchPattern("\xf4\x90\x80\x80", "\xf4\x90\x80\x80"));
-
- // Test UTF16 character matching.
- EXPECT_TRUE(MatchPattern(UTF8ToUTF16("www.google.com"),
- UTF8ToUTF16("*.com")));
- EXPECT_TRUE(MatchPattern(UTF8ToUTF16("Hello*1234"),
- UTF8ToUTF16("He??o\\*1*")));
-
- // Some test cases that might cause naive implementations to exhibit
- // exponential run time or fail.
- EXPECT_TRUE(MatchPattern("Hello", "He********************************o"));
- EXPECT_TRUE(MatchPattern("123456789012345678", "?????????????????*"));
- EXPECT_TRUE(MatchPattern("aaaaaaaaaaab", "a*a*a*a*a*a*a*a*a*a*a*b"));
-}
-
-} // namespace base
diff --git a/base/strings/safe_sprintf_unittest.cc b/base/strings/safe_sprintf_unittest.cc
deleted file mode 100644
index 4a0948b..0000000
--- a/base/strings/safe_sprintf_unittest.cc
+++ /dev/null
@@ -1,765 +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/safe_sprintf.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <string.h>
-
-#include <limits>
-#include <memory>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Death tests on Android are currently very flaky. No need to add more flaky
-// tests, as they just make it hard to spot real problems.
-// TODO(markus): See if the restrictions on Android can eventually be lifted.
-#if defined(GTEST_HAS_DEATH_TEST) && !defined(OS_ANDROID)
-#define ALLOW_DEATH_TEST
-#endif
-
-namespace base {
-namespace strings {
-
-TEST(SafeSPrintfTest, Empty) {
- char buf[2] = { 'X', 'X' };
-
- // Negative buffer size should always result in an error.
- EXPECT_EQ(-1, SafeSNPrintf(buf, static_cast<size_t>(-1), ""));
- EXPECT_EQ('X', buf[0]);
- EXPECT_EQ('X', buf[1]);
-
- // Zero buffer size should always result in an error.
- EXPECT_EQ(-1, SafeSNPrintf(buf, 0, ""));
- EXPECT_EQ('X', buf[0]);
- EXPECT_EQ('X', buf[1]);
-
- // A one-byte buffer should always print a single NUL byte.
- EXPECT_EQ(0, SafeSNPrintf(buf, 1, ""));
- EXPECT_EQ(0, buf[0]);
- EXPECT_EQ('X', buf[1]);
- buf[0] = 'X';
-
- // A larger buffer should leave the trailing bytes unchanged.
- EXPECT_EQ(0, SafeSNPrintf(buf, 2, ""));
- EXPECT_EQ(0, buf[0]);
- EXPECT_EQ('X', buf[1]);
- buf[0] = 'X';
-
- // The same test using SafeSPrintf() instead of SafeSNPrintf().
- EXPECT_EQ(0, SafeSPrintf(buf, ""));
- EXPECT_EQ(0, buf[0]);
- EXPECT_EQ('X', buf[1]);
- buf[0] = 'X';
-}
-
-TEST(SafeSPrintfTest, NoArguments) {
- // Output a text message that doesn't require any substitutions. This
- // is roughly equivalent to calling strncpy() (but unlike strncpy(), it does
- // always add a trailing NUL; it always deduplicates '%' characters).
- static const char text[] = "hello world";
- char ref[20], buf[20];
- memset(ref, 'X', sizeof(ref));
- memcpy(buf, ref, sizeof(buf));
-
- // A negative buffer size should always result in an error.
- EXPECT_EQ(-1, SafeSNPrintf(buf, static_cast<size_t>(-1), text));
- EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf)));
-
- // Zero buffer size should always result in an error.
- EXPECT_EQ(-1, SafeSNPrintf(buf, 0, text));
- EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf)));
-
- // A one-byte buffer should always print a single NUL byte.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSNPrintf(buf, 1, text));
- EXPECT_EQ(0, buf[0]);
- EXPECT_TRUE(!memcmp(buf+1, ref+1, sizeof(buf)-1));
- memcpy(buf, ref, sizeof(buf));
-
- // A larger (but limited) buffer should always leave the trailing bytes
- // unchanged.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSNPrintf(buf, 2, text));
- EXPECT_EQ(text[0], buf[0]);
- EXPECT_EQ(0, buf[1]);
- EXPECT_TRUE(!memcmp(buf+2, ref+2, sizeof(buf)-2));
- memcpy(buf, ref, sizeof(buf));
-
- // A unrestricted buffer length should always leave the trailing bytes
- // unchanged.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1,
- SafeSNPrintf(buf, sizeof(buf), text));
- EXPECT_EQ(std::string(text), std::string(buf));
- EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text),
- sizeof(buf) - sizeof(text)));
- memcpy(buf, ref, sizeof(buf));
-
- // The same test using SafeSPrintf() instead of SafeSNPrintf().
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSPrintf(buf, text));
- EXPECT_EQ(std::string(text), std::string(buf));
- EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text),
- sizeof(buf) - sizeof(text)));
- memcpy(buf, ref, sizeof(buf));
-
- // Check for deduplication of '%' percent characters.
- EXPECT_EQ(1, SafeSPrintf(buf, "%%"));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%%%"));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%X"));
- EXPECT_EQ(3, SafeSPrintf(buf, "%%%%X"));
-#if defined(NDEBUG)
- EXPECT_EQ(1, SafeSPrintf(buf, "%"));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%%"));
- EXPECT_EQ(2, SafeSPrintf(buf, "%X"));
- EXPECT_EQ(3, SafeSPrintf(buf, "%%%X"));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, "%"), "src.1. == '%'");
- EXPECT_DEATH(SafeSPrintf(buf, "%%%"), "src.1. == '%'");
- EXPECT_DEATH(SafeSPrintf(buf, "%X"), "src.1. == '%'");
- EXPECT_DEATH(SafeSPrintf(buf, "%%%X"), "src.1. == '%'");
-#endif
-}
-
-TEST(SafeSPrintfTest, OneArgument) {
- // Test basic single-argument single-character substitution.
- const char text[] = "hello world";
- const char fmt[] = "hello%cworld";
- char ref[20], buf[20];
- memset(ref, 'X', sizeof(buf));
- memcpy(buf, ref, sizeof(buf));
-
- // A negative buffer size should always result in an error.
- EXPECT_EQ(-1, SafeSNPrintf(buf, static_cast<size_t>(-1), fmt, ' '));
- EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf)));
-
- // Zero buffer size should always result in an error.
- EXPECT_EQ(-1, SafeSNPrintf(buf, 0, fmt, ' '));
- EXPECT_TRUE(!memcmp(buf, ref, sizeof(buf)));
-
- // A one-byte buffer should always print a single NUL byte.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1,
- SafeSNPrintf(buf, 1, fmt, ' '));
- EXPECT_EQ(0, buf[0]);
- EXPECT_TRUE(!memcmp(buf+1, ref+1, sizeof(buf)-1));
- memcpy(buf, ref, sizeof(buf));
-
- // A larger (but limited) buffer should always leave the trailing bytes
- // unchanged.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1,
- SafeSNPrintf(buf, 2, fmt, ' '));
- EXPECT_EQ(text[0], buf[0]);
- EXPECT_EQ(0, buf[1]);
- EXPECT_TRUE(!memcmp(buf+2, ref+2, sizeof(buf)-2));
- memcpy(buf, ref, sizeof(buf));
-
- // A unrestricted buffer length should always leave the trailing bytes
- // unchanged.
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1,
- SafeSNPrintf(buf, sizeof(buf), fmt, ' '));
- EXPECT_EQ(std::string(text), std::string(buf));
- EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text),
- sizeof(buf) - sizeof(text)));
- memcpy(buf, ref, sizeof(buf));
-
- // The same test using SafeSPrintf() instead of SafeSNPrintf().
- EXPECT_EQ(static_cast<ssize_t>(sizeof(text))-1, SafeSPrintf(buf, fmt, ' '));
- EXPECT_EQ(std::string(text), std::string(buf));
- EXPECT_TRUE(!memcmp(buf + sizeof(text), ref + sizeof(text),
- sizeof(buf) - sizeof(text)));
- memcpy(buf, ref, sizeof(buf));
-
- // Check for deduplication of '%' percent characters.
- EXPECT_EQ(1, SafeSPrintf(buf, "%%", 0));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%%%", 0));
- EXPECT_EQ(2, SafeSPrintf(buf, "%Y", 0));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%Y", 0));
- EXPECT_EQ(3, SafeSPrintf(buf, "%%%Y", 0));
- EXPECT_EQ(3, SafeSPrintf(buf, "%%%%Y", 0));
-#if defined(NDEBUG)
- EXPECT_EQ(1, SafeSPrintf(buf, "%", 0));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%%", 0));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, "%", 0), "ch");
- EXPECT_DEATH(SafeSPrintf(buf, "%%%", 0), "ch");
-#endif
-}
-
-TEST(SafeSPrintfTest, MissingArg) {
-#if defined(NDEBUG)
- char buf[20];
- EXPECT_EQ(3, SafeSPrintf(buf, "%c%c", 'A'));
- EXPECT_EQ("A%c", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- char buf[20];
- EXPECT_DEATH(SafeSPrintf(buf, "%c%c", 'A'), "cur_arg < max_args");
-#endif
-}
-
-TEST(SafeSPrintfTest, ASANFriendlyBufferTest) {
- // Print into a buffer that is sized exactly to size. ASAN can verify that
- // nobody attempts to write past the end of the buffer.
- // There is a more complicated test in PrintLongString() that covers a lot
- // more edge case, but it is also harder to debug in case of a failure.
- const char kTestString[] = "This is a test";
- std::unique_ptr<char[]> buf(new char[sizeof(kTestString)]);
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kTestString) - 1),
- SafeSNPrintf(buf.get(), sizeof(kTestString), kTestString));
- EXPECT_EQ(std::string(kTestString), std::string(buf.get()));
- EXPECT_EQ(static_cast<ssize_t>(sizeof(kTestString) - 1),
- SafeSNPrintf(buf.get(), sizeof(kTestString), "%s", kTestString));
- EXPECT_EQ(std::string(kTestString), std::string(buf.get()));
-}
-
-TEST(SafeSPrintfTest, NArgs) {
- // Pre-C++11 compilers have a different code path, that can only print
- // up to ten distinct arguments.
- // We test both SafeSPrintf() and SafeSNPrintf(). This makes sure we don't
- // have typos in the copy-n-pasted code that is needed to deal with various
- // numbers of arguments.
- char buf[12];
- EXPECT_EQ(1, SafeSPrintf(buf, "%c", 1));
- EXPECT_EQ("\1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%c%c", 1, 2));
- EXPECT_EQ("\1\2", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%c%c%c", 1, 2, 3));
- EXPECT_EQ("\1\2\3", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%c%c%c%c", 1, 2, 3, 4));
- EXPECT_EQ("\1\2\3\4", std::string(buf));
- EXPECT_EQ(5, SafeSPrintf(buf, "%c%c%c%c%c", 1, 2, 3, 4, 5));
- EXPECT_EQ("\1\2\3\4\5", std::string(buf));
- EXPECT_EQ(6, SafeSPrintf(buf, "%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6));
- EXPECT_EQ("\1\2\3\4\5\6", std::string(buf));
- EXPECT_EQ(7, SafeSPrintf(buf, "%c%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6, 7));
- EXPECT_EQ("\1\2\3\4\5\6\7", std::string(buf));
- EXPECT_EQ(8, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6, 7, 8));
- EXPECT_EQ("\1\2\3\4\5\6\7\10", std::string(buf));
- EXPECT_EQ(9, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8, 9));
- EXPECT_EQ("\1\2\3\4\5\6\7\10\11", std::string(buf));
- EXPECT_EQ(10, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
-
- // Repeat all the tests with SafeSNPrintf() instead of SafeSPrintf().
- EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12", std::string(buf));
- EXPECT_EQ(1, SafeSNPrintf(buf, 11, "%c", 1));
- EXPECT_EQ("\1", std::string(buf));
- EXPECT_EQ(2, SafeSNPrintf(buf, 11, "%c%c", 1, 2));
- EXPECT_EQ("\1\2", std::string(buf));
- EXPECT_EQ(3, SafeSNPrintf(buf, 11, "%c%c%c", 1, 2, 3));
- EXPECT_EQ("\1\2\3", std::string(buf));
- EXPECT_EQ(4, SafeSNPrintf(buf, 11, "%c%c%c%c", 1, 2, 3, 4));
- EXPECT_EQ("\1\2\3\4", std::string(buf));
- EXPECT_EQ(5, SafeSNPrintf(buf, 11, "%c%c%c%c%c", 1, 2, 3, 4, 5));
- EXPECT_EQ("\1\2\3\4\5", std::string(buf));
- EXPECT_EQ(6, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6));
- EXPECT_EQ("\1\2\3\4\5\6", std::string(buf));
- EXPECT_EQ(7, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c", 1, 2, 3, 4, 5, 6, 7));
- EXPECT_EQ("\1\2\3\4\5\6\7", std::string(buf));
- EXPECT_EQ(8, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8));
- EXPECT_EQ("\1\2\3\4\5\6\7\10", std::string(buf));
- EXPECT_EQ(9, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8, 9));
- EXPECT_EQ("\1\2\3\4\5\6\7\10\11", std::string(buf));
- EXPECT_EQ(10, SafeSNPrintf(buf, 11, "%c%c%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
- EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12", std::string(buf));
-
- EXPECT_EQ(11, SafeSPrintf(buf, "%c%c%c%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12\13", std::string(buf));
- EXPECT_EQ(11, SafeSNPrintf(buf, 12, "%c%c%c%c%c%c%c%c%c%c%c",
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11));
- EXPECT_EQ("\1\2\3\4\5\6\7\10\11\12\13", std::string(buf));
-}
-
-TEST(SafeSPrintfTest, DataTypes) {
- char buf[40];
-
- // Bytes
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint8_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%d", (uint8_t)-1));
- EXPECT_EQ("255", std::string(buf));
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int8_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int8_t)-1));
- EXPECT_EQ("-1", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%d", (int8_t)-128));
- EXPECT_EQ("-128", std::string(buf));
-
- // Half-words
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint16_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(5, SafeSPrintf(buf, "%d", (uint16_t)-1));
- EXPECT_EQ("65535", std::string(buf));
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int16_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int16_t)-1));
- EXPECT_EQ("-1", std::string(buf));
- EXPECT_EQ(6, SafeSPrintf(buf, "%d", (int16_t)-32768));
- EXPECT_EQ("-32768", std::string(buf));
-
- // Words
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint32_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(10, SafeSPrintf(buf, "%d", (uint32_t)-1));
- EXPECT_EQ("4294967295", std::string(buf));
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int32_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int32_t)-1));
- EXPECT_EQ("-1", std::string(buf));
- // Work-around for an limitation of C90
- EXPECT_EQ(11, SafeSPrintf(buf, "%d", (int32_t)-2147483647-1));
- EXPECT_EQ("-2147483648", std::string(buf));
-
- // Quads
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (uint64_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(20, SafeSPrintf(buf, "%d", (uint64_t)-1));
- EXPECT_EQ("18446744073709551615", std::string(buf));
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", (int64_t)1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%d", (int64_t)-1));
- EXPECT_EQ("-1", std::string(buf));
- // Work-around for an limitation of C90
- EXPECT_EQ(20, SafeSPrintf(buf, "%d", (int64_t)-9223372036854775807LL-1));
- EXPECT_EQ("-9223372036854775808", std::string(buf));
-
- // Strings (both const and mutable).
- EXPECT_EQ(4, SafeSPrintf(buf, "test"));
- EXPECT_EQ("test", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, buf));
- EXPECT_EQ("test", std::string(buf));
-
- // Pointer
- char addr[20];
- sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)buf);
- SafeSPrintf(buf, "%p", buf);
- EXPECT_EQ(std::string(addr), std::string(buf));
- SafeSPrintf(buf, "%p", (const char *)buf);
- EXPECT_EQ(std::string(addr), std::string(buf));
- sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)sprintf);
- SafeSPrintf(buf, "%p", sprintf);
- EXPECT_EQ(std::string(addr), std::string(buf));
-
- // Padding for pointers is a little more complicated because of the "0x"
- // prefix. Padding with '0' zeros is relatively straight-forward, but
- // padding with ' ' spaces requires more effort.
- sprintf(addr, "0x%017llX", (unsigned long long)(uintptr_t)buf);
- SafeSPrintf(buf, "%019p", buf);
- EXPECT_EQ(std::string(addr), std::string(buf));
- sprintf(addr, "0x%llX", (unsigned long long)(uintptr_t)buf);
- memset(addr, ' ',
- (char*)memmove(addr + sizeof(addr) - strlen(addr) - 1,
- addr, strlen(addr)+1) - addr);
- SafeSPrintf(buf, "%19p", buf);
- EXPECT_EQ(std::string(addr), std::string(buf));
-}
-
-namespace {
-void PrintLongString(char* buf, size_t sz) {
- // Output a reasonably complex expression into a limited-size buffer.
- // At least one byte is available for writing the NUL character.
- CHECK_GT(sz, static_cast<size_t>(0));
-
- // Allocate slightly more space, so that we can verify that SafeSPrintf()
- // never writes past the end of the buffer.
- std::unique_ptr<char[]> tmp(new char[sz + 2]);
- memset(tmp.get(), 'X', sz+2);
-
- // Use SafeSPrintf() to output a complex list of arguments:
- // - test padding and truncating %c single characters.
- // - test truncating %s simple strings.
- // - test mismatching arguments and truncating (for %d != %s).
- // - test zero-padding and truncating %x hexadecimal numbers.
- // - test outputting and truncating %d MININT.
- // - test outputting and truncating %p arbitrary pointer values.
- // - test outputting, padding and truncating NULL-pointer %s strings.
- char* out = tmp.get();
- size_t out_sz = sz;
- size_t len;
- for (std::unique_ptr<char[]> perfect_buf;;) {
- size_t needed =
- SafeSNPrintf(out, out_sz,
-#if defined(NDEBUG)
- "A%2cong %s: %d %010X %d %p%7s", 'l', "string", "",
-#else
- "A%2cong %s: %%d %010X %d %p%7s", 'l', "string",
-#endif
- 0xDEADBEEF, std::numeric_limits<intptr_t>::min(),
- PrintLongString, static_cast<char*>(nullptr)) +
- 1;
-
- // Various sanity checks:
- // The numbered of characters needed to print the full string should always
- // be bigger or equal to the bytes that have actually been output.
- len = strlen(tmp.get());
- CHECK_GE(needed, len+1);
-
- // The number of characters output should always fit into the buffer that
- // was passed into SafeSPrintf().
- CHECK_LT(len, out_sz);
-
- // The output is always terminated with a NUL byte (actually, this test is
- // always going to pass, as strlen() already verified this)
- EXPECT_FALSE(tmp[len]);
-
- // ASAN can check that we are not overwriting buffers, iff we make sure the
- // buffer is exactly the size that we are expecting to be written. After
- // running SafeSNPrintf() the first time, it is possible to compute the
- // correct buffer size for this test. So, allocate a second buffer and run
- // the exact same SafeSNPrintf() command again.
- if (!perfect_buf.get()) {
- out_sz = std::min(needed, sz);
- out = new char[out_sz];
- perfect_buf.reset(out);
- } else {
- break;
- }
- }
-
- // All trailing bytes are unchanged.
- for (size_t i = len+1; i < sz+2; ++i)
- EXPECT_EQ('X', tmp[i]);
-
- // The text that was generated by SafeSPrintf() should always match the
- // equivalent text generated by sprintf(). Please note that the format
- // string for sprintf() is not complicated, as it does not have the
- // benefit of getting type information from the C++ compiler.
- //
- // N.B.: It would be so much cleaner to use snprintf(). But unfortunately,
- // Visual Studio doesn't support this function, and the work-arounds
- // are all really awkward.
- char ref[256];
- CHECK_LE(sz, sizeof(ref));
- sprintf(ref, "A long string: %%d 00DEADBEEF %lld 0x%llX <NULL>",
- static_cast<long long>(std::numeric_limits<intptr_t>::min()),
- static_cast<unsigned long long>(
- reinterpret_cast<uintptr_t>(PrintLongString)));
- ref[sz-1] = '\000';
-
-#if defined(NDEBUG)
- const size_t kSSizeMax = std::numeric_limits<ssize_t>::max();
-#else
- const size_t kSSizeMax = internal::GetSafeSPrintfSSizeMaxForTest();
-#endif
-
- // Compare the output from SafeSPrintf() to the one from sprintf().
- EXPECT_EQ(std::string(ref).substr(0, kSSizeMax-1), std::string(tmp.get()));
-
- // We allocated a slightly larger buffer, so that we could perform some
- // extra sanity checks. Now that the tests have all passed, we copy the
- // data to the output buffer that the caller provided.
- memcpy(buf, tmp.get(), len+1);
-}
-
-#if !defined(NDEBUG)
-class ScopedSafeSPrintfSSizeMaxSetter {
- public:
- ScopedSafeSPrintfSSizeMaxSetter(size_t sz) {
- old_ssize_max_ = internal::GetSafeSPrintfSSizeMaxForTest();
- internal::SetSafeSPrintfSSizeMaxForTest(sz);
- }
-
- ~ScopedSafeSPrintfSSizeMaxSetter() {
- internal::SetSafeSPrintfSSizeMaxForTest(old_ssize_max_);
- }
-
- private:
- size_t old_ssize_max_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedSafeSPrintfSSizeMaxSetter);
-};
-#endif
-
-} // anonymous namespace
-
-TEST(SafeSPrintfTest, Truncation) {
- // We use PrintLongString() to print a complex long string and then
- // truncate to all possible lengths. This ends up exercising a lot of
- // different code paths in SafeSPrintf() and IToASCII(), as truncation can
- // happen in a lot of different states.
- char ref[256];
- PrintLongString(ref, sizeof(ref));
- for (size_t i = strlen(ref)+1; i; --i) {
- char buf[sizeof(ref)];
- PrintLongString(buf, i);
- EXPECT_EQ(std::string(ref, i - 1), std::string(buf));
- }
-
- // When compiling in debug mode, we have the ability to fake a small
- // upper limit for the maximum value that can be stored in an ssize_t.
- // SafeSPrintf() uses this upper limit to determine how many bytes it will
- // write to the buffer, even if the caller claimed a bigger buffer size.
- // Repeat the truncation test and verify that this other code path in
- // SafeSPrintf() works correctly, too.
-#if !defined(NDEBUG)
- for (size_t i = strlen(ref)+1; i > 1; --i) {
- ScopedSafeSPrintfSSizeMaxSetter ssize_max_setter(i);
- char buf[sizeof(ref)];
- PrintLongString(buf, sizeof(buf));
- EXPECT_EQ(std::string(ref, i - 1), std::string(buf));
- }
-
- // kSSizeMax is also used to constrain the maximum amount of padding, before
- // SafeSPrintf() detects an error in the format string.
- ScopedSafeSPrintfSSizeMaxSetter ssize_max_setter(100);
- char buf[256];
- EXPECT_EQ(99, SafeSPrintf(buf, "%99c", ' '));
- EXPECT_EQ(std::string(99, ' '), std::string(buf));
- *buf = '\000';
-#if defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, "%100c", ' '), "padding <= max_padding");
-#endif
- EXPECT_EQ(0, *buf);
-#endif
-}
-
-TEST(SafeSPrintfTest, Padding) {
- char buf[40], fmt[40];
-
- // Chars %c
- EXPECT_EQ(1, SafeSPrintf(buf, "%c", 'A'));
- EXPECT_EQ("A", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%2c", 'A'));
- EXPECT_EQ(" A", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%02c", 'A'));
- EXPECT_EQ(" A", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%-2c", 'A'));
- EXPECT_EQ("%-2c", std::string(buf));
- SafeSPrintf(fmt, "%%%dc", std::numeric_limits<ssize_t>::max() - 1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1, SafeSPrintf(buf, fmt, 'A'));
- SafeSPrintf(fmt, "%%%dc",
- static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, fmt, 'A'));
- EXPECT_EQ("%c", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, fmt, 'A'), "padding <= max_padding");
-#endif
-
- // Octal %o
- EXPECT_EQ(1, SafeSPrintf(buf, "%o", 1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%2o", 1));
- EXPECT_EQ(" 1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%02o", 1));
- EXPECT_EQ("01", std::string(buf));
- EXPECT_EQ(12, SafeSPrintf(buf, "%12o", -1));
- EXPECT_EQ(" 37777777777", std::string(buf));
- EXPECT_EQ(12, SafeSPrintf(buf, "%012o", -1));
- EXPECT_EQ("037777777777", std::string(buf));
- EXPECT_EQ(23, SafeSPrintf(buf, "%23o", -1LL));
- EXPECT_EQ(" 1777777777777777777777", std::string(buf));
- EXPECT_EQ(23, SafeSPrintf(buf, "%023o", -1LL));
- EXPECT_EQ("01777777777777777777777", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%2o", 0111));
- EXPECT_EQ("111", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%-2o", 1));
- EXPECT_EQ("%-2o", std::string(buf));
- SafeSPrintf(fmt, "%%%do", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, 1));
- EXPECT_EQ(" ", std::string(buf));
- SafeSPrintf(fmt, "%%0%do", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, 1));
- EXPECT_EQ("000", std::string(buf));
- SafeSPrintf(fmt, "%%%do",
- static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1));
- EXPECT_EQ("%o", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding");
-#endif
-
- // Decimals %d
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", 1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%2d", 1));
- EXPECT_EQ(" 1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%02d", 1));
- EXPECT_EQ("01", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%3d", -1));
- EXPECT_EQ(" -1", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%03d", -1));
- EXPECT_EQ("-01", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%2d", 111));
- EXPECT_EQ("111", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%2d", -111));
- EXPECT_EQ("-111", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%-2d", 1));
- EXPECT_EQ("%-2d", std::string(buf));
- SafeSPrintf(fmt, "%%%dd", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, 1));
- EXPECT_EQ(" ", std::string(buf));
- SafeSPrintf(fmt, "%%0%dd", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, 1));
- EXPECT_EQ("000", std::string(buf));
- SafeSPrintf(fmt, "%%%dd",
- static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1));
- EXPECT_EQ("%d", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding");
-#endif
-
- // Hex %X
- EXPECT_EQ(1, SafeSPrintf(buf, "%X", 1));
- EXPECT_EQ("1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%2X", 1));
- EXPECT_EQ(" 1", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%02X", 1));
- EXPECT_EQ("01", std::string(buf));
- EXPECT_EQ(9, SafeSPrintf(buf, "%9X", -1));
- EXPECT_EQ(" FFFFFFFF", std::string(buf));
- EXPECT_EQ(9, SafeSPrintf(buf, "%09X", -1));
- EXPECT_EQ("0FFFFFFFF", std::string(buf));
- EXPECT_EQ(17, SafeSPrintf(buf, "%17X", -1LL));
- EXPECT_EQ(" FFFFFFFFFFFFFFFF", std::string(buf));
- EXPECT_EQ(17, SafeSPrintf(buf, "%017X", -1LL));
- EXPECT_EQ("0FFFFFFFFFFFFFFFF", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%2X", 0x111));
- EXPECT_EQ("111", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%-2X", 1));
- EXPECT_EQ("%-2X", std::string(buf));
- SafeSPrintf(fmt, "%%%dX", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, 1));
- EXPECT_EQ(" ", std::string(buf));
- SafeSPrintf(fmt, "%%0%dX", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, 1));
- EXPECT_EQ("000", std::string(buf));
- SafeSPrintf(fmt, "%%%dX",
- static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1));
- EXPECT_EQ("%X", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding");
-#endif
-
- // Pointer %p
- EXPECT_EQ(3, SafeSPrintf(buf, "%p", (void*)1));
- EXPECT_EQ("0x1", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%4p", (void*)1));
- EXPECT_EQ(" 0x1", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%04p", (void*)1));
- EXPECT_EQ("0x01", std::string(buf));
- EXPECT_EQ(5, SafeSPrintf(buf, "%4p", (void*)0x111));
- EXPECT_EQ("0x111", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%-2p", (void*)1));
- EXPECT_EQ("%-2p", std::string(buf));
- SafeSPrintf(fmt, "%%%dp", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, (void*)1));
- EXPECT_EQ(" ", std::string(buf));
- SafeSPrintf(fmt, "%%0%dp", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, (void*)1));
- EXPECT_EQ("0x0", std::string(buf));
- SafeSPrintf(fmt, "%%%dp",
- static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, fmt, 1));
- EXPECT_EQ("%p", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, fmt, 1), "padding <= max_padding");
-#endif
-
- // String
- EXPECT_EQ(1, SafeSPrintf(buf, "%s", "A"));
- EXPECT_EQ("A", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%2s", "A"));
- EXPECT_EQ(" A", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%02s", "A"));
- EXPECT_EQ(" A", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%2s", "AAA"));
- EXPECT_EQ("AAA", std::string(buf));
- EXPECT_EQ(4, SafeSPrintf(buf, "%-2s", "A"));
- EXPECT_EQ("%-2s", std::string(buf));
- SafeSPrintf(fmt, "%%%ds", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, "A"));
- EXPECT_EQ(" ", std::string(buf));
- SafeSPrintf(fmt, "%%0%ds", std::numeric_limits<ssize_t>::max()-1);
- EXPECT_EQ(std::numeric_limits<ssize_t>::max()-1,
- SafeSNPrintf(buf, 4, fmt, "A"));
- EXPECT_EQ(" ", std::string(buf));
- SafeSPrintf(fmt, "%%%ds",
- static_cast<size_t>(std::numeric_limits<ssize_t>::max()));
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, fmt, "A"));
- EXPECT_EQ("%s", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, fmt, "A"), "padding <= max_padding");
-#endif
-}
-
-TEST(SafeSPrintfTest, EmbeddedNul) {
- char buf[] = { 'X', 'X', 'X', 'X' };
- EXPECT_EQ(2, SafeSPrintf(buf, "%3c", 0));
- EXPECT_EQ(' ', buf[0]);
- EXPECT_EQ(' ', buf[1]);
- EXPECT_EQ(0, buf[2]);
- EXPECT_EQ('X', buf[3]);
-
- // Check handling of a NUL format character. N.B. this takes two different
- // code paths depending on whether we are actually passing arguments. If
- // we don't have any arguments, we are running in the fast-path code, that
- // looks (almost) like a strncpy().
-#if defined(NDEBUG)
- EXPECT_EQ(2, SafeSPrintf(buf, "%%%"));
- EXPECT_EQ("%%", std::string(buf));
- EXPECT_EQ(2, SafeSPrintf(buf, "%%%", 0));
- EXPECT_EQ("%%", std::string(buf));
-#elif defined(ALLOW_DEATH_TEST)
- EXPECT_DEATH(SafeSPrintf(buf, "%%%"), "src.1. == '%'");
- EXPECT_DEATH(SafeSPrintf(buf, "%%%", 0), "ch");
-#endif
-}
-
-TEST(SafeSPrintfTest, EmitNULL) {
- char buf[40];
-#if defined(__GNUC__)
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wconversion-null"
-#endif
- EXPECT_EQ(1, SafeSPrintf(buf, "%d", NULL));
- EXPECT_EQ("0", std::string(buf));
- EXPECT_EQ(3, SafeSPrintf(buf, "%p", NULL));
- EXPECT_EQ("0x0", std::string(buf));
- EXPECT_EQ(6, SafeSPrintf(buf, "%s", NULL));
- EXPECT_EQ("<NULL>", std::string(buf));
-#if defined(__GCC__)
-#pragma GCC diagnostic pop
-#endif
-}
-
-TEST(SafeSPrintfTest, PointerSize) {
- // The internal data representation is a 64bit value, independent of the
- // native word size. We want to perform sign-extension for signed integers,
- // but we want to avoid doing so for pointer types. This could be a
- // problem on systems, where pointers are only 32bit. This tests verifies
- // that there is no such problem.
- char *str = reinterpret_cast<char *>(0x80000000u);
- void *ptr = str;
- char buf[40];
- EXPECT_EQ(10, SafeSPrintf(buf, "%p", str));
- EXPECT_EQ("0x80000000", std::string(buf));
- EXPECT_EQ(10, SafeSPrintf(buf, "%p", ptr));
- EXPECT_EQ("0x80000000", std::string(buf));
-}
-
-} // namespace strings
-} // namespace base
diff --git a/base/strings/strcat_unittest.cc b/base/strings/strcat_unittest.cc
deleted file mode 100644
index cf2db51..0000000
--- a/base/strings/strcat_unittest.cc
+++ /dev/null
@@ -1,67 +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/strings/strcat.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(StrCat, 8Bit) {
- EXPECT_EQ("", StrCat({""}));
- EXPECT_EQ("1", StrCat({"1"}));
- EXPECT_EQ("122", StrCat({"1", "22"}));
- EXPECT_EQ("122333", StrCat({"1", "22", "333"}));
- EXPECT_EQ("1223334444", StrCat({"1", "22", "333", "4444"}));
- EXPECT_EQ("122333444455555", StrCat({"1", "22", "333", "4444", "55555"}));
-}
-
-TEST(StrCat, 16Bit) {
- string16 arg1 = ASCIIToUTF16("1");
- string16 arg2 = ASCIIToUTF16("22");
- string16 arg3 = ASCIIToUTF16("333");
-
- EXPECT_EQ(ASCIIToUTF16(""), StrCat({string16()}));
- EXPECT_EQ(ASCIIToUTF16("1"), StrCat({arg1}));
- EXPECT_EQ(ASCIIToUTF16("122"), StrCat({arg1, arg2}));
- EXPECT_EQ(ASCIIToUTF16("122333"), StrCat({arg1, arg2, arg3}));
-}
-
-TEST(StrAppend, 8Bit) {
- std::string result;
-
- result = "foo";
- StrAppend(&result, {std::string()});
- EXPECT_EQ("foo", result);
-
- result = "foo";
- StrAppend(&result, {"1"});
- EXPECT_EQ("foo1", result);
-
- result = "foo";
- StrAppend(&result, {"1", "22", "333"});
- EXPECT_EQ("foo122333", result);
-}
-
-TEST(StrAppend, 16Bit) {
- string16 arg1 = ASCIIToUTF16("1");
- string16 arg2 = ASCIIToUTF16("22");
- string16 arg3 = ASCIIToUTF16("333");
-
- string16 result;
-
- result = ASCIIToUTF16("foo");
- StrAppend(&result, {string16()});
- EXPECT_EQ(ASCIIToUTF16("foo"), result);
-
- result = ASCIIToUTF16("foo");
- StrAppend(&result, {arg1});
- EXPECT_EQ(ASCIIToUTF16("foo1"), result);
-
- result = ASCIIToUTF16("foo");
- StrAppend(&result, {arg1, arg2, arg3});
- EXPECT_EQ(ASCIIToUTF16("foo122333"), result);
-}
-
-} // namespace base
diff --git a/base/strings/string16_unittest.cc b/base/strings/string16_unittest.cc
deleted file mode 100644
index 0d2ca80..0000000
--- a/base/strings/string16_unittest.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 <sstream>
-#include <unordered_set>
-
-#include "base/strings/string16.h"
-
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// We define a custom operator<< for string16 so we can use it with logging.
-// This tests that conversion.
-TEST(String16Test, OutputStream) {
- // Basic stream test.
- {
- std::ostringstream stream;
- stream << "Empty '" << string16() << "' standard '"
- << string16(ASCIIToUTF16("Hello, world")) << "'";
- EXPECT_STREQ("Empty '' standard 'Hello, world'",
- stream.str().c_str());
- }
-
- // Interesting edge cases.
- {
- // These should each get converted to the invalid character: EF BF BD.
- string16 initial_surrogate;
- initial_surrogate.push_back(0xd800);
- string16 final_surrogate;
- final_surrogate.push_back(0xdc00);
-
- // Old italic A = U+10300, will get converted to: F0 90 8C 80 'z'.
- string16 surrogate_pair;
- surrogate_pair.push_back(0xd800);
- surrogate_pair.push_back(0xdf00);
- surrogate_pair.push_back('z');
-
- // Will get converted to the invalid char + 's': EF BF BD 's'.
- string16 unterminated_surrogate;
- unterminated_surrogate.push_back(0xd800);
- unterminated_surrogate.push_back('s');
-
- std::ostringstream stream;
- stream << initial_surrogate << "," << final_surrogate << ","
- << surrogate_pair << "," << unterminated_surrogate;
-
- EXPECT_STREQ("\xef\xbf\xbd,\xef\xbf\xbd,\xf0\x90\x8c\x80z,\xef\xbf\xbds",
- stream.str().c_str());
- }
-}
-
-TEST(String16Test, Hash) {
- string16 str1 = ASCIIToUTF16("hello");
- string16 str2 = ASCIIToUTF16("world");
-
- std::unordered_set<string16> set;
-
- set.insert(str1);
- EXPECT_EQ(1u, set.count(str1));
- EXPECT_EQ(0u, set.count(str2));
-}
-
-} // namespace base
diff --git a/base/strings/string16_unittest.nc b/base/strings/string16_unittest.nc
deleted file mode 100644
index 5186a45..0000000
--- a/base/strings/string16_unittest.nc
+++ /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.
-
-// This is a "No Compile Test".
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/strings/string16.h"
-
-#if defined(NCTEST_NO_KOENIG_LOOKUP_FOR_STRING16) // [r"use of undeclared identifier 'ShouldNotBeFound'"]
-
-// base::string16 is declared as a typedef. It should not cause other functions
-// in base to be found via Argument-dependent lookup.
-
-namespace base {
-void ShouldNotBeFound(const base::string16& arg) {}
-}
-
-// Intentionally not in base:: namespace.
-void WontCompile() {
- base::string16 s;
- ShouldNotBeFound(s);
-}
-
-#endif
diff --git a/base/strings/string_number_conversions_unittest.cc b/base/strings/string_number_conversions_unittest.cc
deleted file mode 100644
index d969450..0000000
--- a/base/strings/string_number_conversions_unittest.cc
+++ /dev/null
@@ -1,905 +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/strings/string_number_conversions.h"
-
-#include <errno.h>
-#include <limits.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-
-#include <cmath>
-#include <limits>
-
-#include "base/bit_cast.h"
-#include "base/format_macros.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-template <typename INT>
-struct NumberToStringTest {
- INT num;
- const char* sexpected;
- const char* uexpected;
-};
-
-} // namespace
-
-TEST(StringNumberConversionsTest, NumberToString) {
- static const NumberToStringTest<int> int_tests[] = {
- {0, "0", "0"},
- {-1, "-1", "4294967295"},
- {std::numeric_limits<int>::max(), "2147483647", "2147483647"},
- {std::numeric_limits<int>::min(), "-2147483648", "2147483648"},
- };
- static const NumberToStringTest<int64_t> int64_tests[] = {
- {0, "0", "0"},
- {-1, "-1", "18446744073709551615"},
- {
- std::numeric_limits<int64_t>::max(), "9223372036854775807",
- "9223372036854775807",
- },
- {std::numeric_limits<int64_t>::min(), "-9223372036854775808",
- "9223372036854775808"},
- };
-
- for (size_t i = 0; i < arraysize(int_tests); ++i) {
- const NumberToStringTest<int>& test = int_tests[i];
- EXPECT_EQ(NumberToString(test.num), test.sexpected);
- EXPECT_EQ(NumberToString16(test.num), UTF8ToUTF16(test.sexpected));
- EXPECT_EQ(NumberToString(static_cast<unsigned>(test.num)), test.uexpected);
- EXPECT_EQ(NumberToString16(static_cast<unsigned>(test.num)),
- UTF8ToUTF16(test.uexpected));
- }
- for (size_t i = 0; i < arraysize(int64_tests); ++i) {
- const NumberToStringTest<int64_t>& test = int64_tests[i];
- EXPECT_EQ(NumberToString(test.num), test.sexpected);
- EXPECT_EQ(NumberToString16(test.num), UTF8ToUTF16(test.sexpected));
- EXPECT_EQ(NumberToString(static_cast<uint64_t>(test.num)), test.uexpected);
- EXPECT_EQ(NumberToString16(static_cast<uint64_t>(test.num)),
- UTF8ToUTF16(test.uexpected));
- }
-}
-
-TEST(StringNumberConversionsTest, Uint64ToString) {
- static const struct {
- uint64_t input;
- std::string output;
- } cases[] = {
- {0, "0"},
- {42, "42"},
- {INT_MAX, "2147483647"},
- {std::numeric_limits<uint64_t>::max(), "18446744073709551615"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i)
- EXPECT_EQ(cases[i].output, NumberToString(cases[i].input));
-}
-
-TEST(StringNumberConversionsTest, SizeTToString) {
- size_t size_t_max = std::numeric_limits<size_t>::max();
- std::string size_t_max_string = StringPrintf("%" PRIuS, size_t_max);
-
- static const struct {
- size_t input;
- std::string output;
- } cases[] = {
- {0, "0"},
- {9, "9"},
- {42, "42"},
- {INT_MAX, "2147483647"},
- {2147483648U, "2147483648"},
-#if SIZE_MAX > 4294967295U
- {99999999999U, "99999999999"},
-#endif
- {size_t_max, size_t_max_string},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i)
- EXPECT_EQ(cases[i].output, NumberToString(cases[i].input));
-}
-
-TEST(StringNumberConversionsTest, StringToInt) {
- static const struct {
- std::string input;
- int output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 42, true},
- {"42\x99", 42, false},
- {"\x99" "42\x99", 0, false},
- {"-2147483648", INT_MIN, true},
- {"2147483647", INT_MAX, true},
- {"", 0, false},
- {" 42", 42, false},
- {"42 ", 42, false},
- {"\t\n\v\f\r 42", 42, false},
- {"blah42", 0, false},
- {"42blah", 42, false},
- {"blah42blah", 0, false},
- {"-273.15", -273, false},
- {"+98.6", 98, false},
- {"--123", 0, false},
- {"++123", 0, false},
- {"-+123", 0, false},
- {"+-123", 0, false},
- {"-", 0, false},
- {"-2147483649", INT_MIN, false},
- {"-99999999999", INT_MIN, false},
- {"2147483648", INT_MAX, false},
- {"99999999999", INT_MAX, false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- int output = cases[i].output ^ 1; // Ensure StringToInt wrote something.
- EXPECT_EQ(cases[i].success, StringToInt(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
-
- string16 utf16_input = UTF8ToUTF16(cases[i].input);
- output = cases[i].output ^ 1; // Ensure StringToInt wrote something.
- EXPECT_EQ(cases[i].success, StringToInt(utf16_input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
-
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "6\06";
- std::string input_string(input, arraysize(input) - 1);
- int output;
- EXPECT_FALSE(StringToInt(input_string, &output));
- EXPECT_EQ(6, output);
-
- string16 utf16_input = UTF8ToUTF16(input_string);
- output = 0;
- EXPECT_FALSE(StringToInt(utf16_input, &output));
- EXPECT_EQ(6, output);
-
- output = 0;
- const char16 negative_wide_input[] = { 0xFF4D, '4', '2', 0};
- EXPECT_FALSE(StringToInt(string16(negative_wide_input), &output));
- EXPECT_EQ(0, output);
-}
-
-TEST(StringNumberConversionsTest, StringToUint) {
- static const struct {
- std::string input;
- unsigned output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 42, true},
- {"42\x99", 42, false},
- {"\x99" "42\x99", 0, false},
- {"-2147483648", 0, false},
- {"2147483647", INT_MAX, true},
- {"", 0, false},
- {" 42", 42, false},
- {"42 ", 42, false},
- {"\t\n\v\f\r 42", 42, false},
- {"blah42", 0, false},
- {"42blah", 42, false},
- {"blah42blah", 0, false},
- {"-273.15", 0, false},
- {"+98.6", 98, false},
- {"--123", 0, false},
- {"++123", 0, false},
- {"-+123", 0, false},
- {"+-123", 0, false},
- {"-", 0, false},
- {"-2147483649", 0, false},
- {"-99999999999", 0, false},
- {"4294967295", UINT_MAX, true},
- {"4294967296", UINT_MAX, false},
- {"99999999999", UINT_MAX, false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- unsigned output =
- cases[i].output ^ 1; // Ensure StringToUint wrote something.
- EXPECT_EQ(cases[i].success, StringToUint(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
-
- string16 utf16_input = UTF8ToUTF16(cases[i].input);
- output = cases[i].output ^ 1; // Ensure StringToUint wrote something.
- EXPECT_EQ(cases[i].success, StringToUint(utf16_input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
-
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "6\06";
- std::string input_string(input, arraysize(input) - 1);
- unsigned output;
- EXPECT_FALSE(StringToUint(input_string, &output));
- EXPECT_EQ(6U, output);
-
- string16 utf16_input = UTF8ToUTF16(input_string);
- output = 0;
- EXPECT_FALSE(StringToUint(utf16_input, &output));
- EXPECT_EQ(6U, output);
-
- output = 0;
- const char16 negative_wide_input[] = { 0xFF4D, '4', '2', 0};
- EXPECT_FALSE(StringToUint(string16(negative_wide_input), &output));
- EXPECT_EQ(0U, output);
-}
-
-TEST(StringNumberConversionsTest, StringToInt64) {
- static const struct {
- std::string input;
- int64_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 42, true},
- {"-2147483648", INT_MIN, true},
- {"2147483647", INT_MAX, true},
- {"-2147483649", INT64_C(-2147483649), true},
- {"-99999999999", INT64_C(-99999999999), true},
- {"2147483648", INT64_C(2147483648), true},
- {"99999999999", INT64_C(99999999999), true},
- {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
- {"-9223372036854775808", std::numeric_limits<int64_t>::min(), true},
- {"09", 9, true},
- {"-09", -9, true},
- {"", 0, false},
- {" 42", 42, false},
- {"42 ", 42, false},
- {"0x42", 0, false},
- {"\t\n\v\f\r 42", 42, false},
- {"blah42", 0, false},
- {"42blah", 42, false},
- {"blah42blah", 0, false},
- {"-273.15", -273, false},
- {"+98.6", 98, false},
- {"--123", 0, false},
- {"++123", 0, false},
- {"-+123", 0, false},
- {"+-123", 0, false},
- {"-", 0, false},
- {"-9223372036854775809", std::numeric_limits<int64_t>::min(), false},
- {"-99999999999999999999", std::numeric_limits<int64_t>::min(), false},
- {"9223372036854775808", std::numeric_limits<int64_t>::max(), false},
- {"99999999999999999999", std::numeric_limits<int64_t>::max(), false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- int64_t output = 0;
- EXPECT_EQ(cases[i].success, StringToInt64(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
-
- string16 utf16_input = UTF8ToUTF16(cases[i].input);
- output = 0;
- EXPECT_EQ(cases[i].success, StringToInt64(utf16_input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
-
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "6\06";
- std::string input_string(input, arraysize(input) - 1);
- int64_t output;
- EXPECT_FALSE(StringToInt64(input_string, &output));
- EXPECT_EQ(6, output);
-
- string16 utf16_input = UTF8ToUTF16(input_string);
- output = 0;
- EXPECT_FALSE(StringToInt64(utf16_input, &output));
- EXPECT_EQ(6, output);
-}
-
-TEST(StringNumberConversionsTest, StringToUint64) {
- static const struct {
- std::string input;
- uint64_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 42, true},
- {"-2147483648", 0, false},
- {"2147483647", INT_MAX, true},
- {"-2147483649", 0, false},
- {"-99999999999", 0, false},
- {"2147483648", UINT64_C(2147483648), true},
- {"99999999999", UINT64_C(99999999999), true},
- {"9223372036854775807", std::numeric_limits<int64_t>::max(), true},
- {"-9223372036854775808", 0, false},
- {"09", 9, true},
- {"-09", 0, false},
- {"", 0, false},
- {" 42", 42, false},
- {"42 ", 42, false},
- {"0x42", 0, false},
- {"\t\n\v\f\r 42", 42, false},
- {"blah42", 0, false},
- {"42blah", 42, false},
- {"blah42blah", 0, false},
- {"-273.15", 0, false},
- {"+98.6", 98, false},
- {"--123", 0, false},
- {"++123", 0, false},
- {"-+123", 0, false},
- {"+-123", 0, false},
- {"-", 0, false},
- {"-9223372036854775809", 0, false},
- {"-99999999999999999999", 0, false},
- {"9223372036854775808", UINT64_C(9223372036854775808), true},
- {"99999999999999999999", std::numeric_limits<uint64_t>::max(), false},
- {"18446744073709551615", std::numeric_limits<uint64_t>::max(), true},
- {"18446744073709551616", std::numeric_limits<uint64_t>::max(), false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- uint64_t output = 0;
- EXPECT_EQ(cases[i].success, StringToUint64(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
-
- string16 utf16_input = UTF8ToUTF16(cases[i].input);
- output = 0;
- EXPECT_EQ(cases[i].success, StringToUint64(utf16_input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
-
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "6\06";
- std::string input_string(input, arraysize(input) - 1);
- uint64_t output;
- EXPECT_FALSE(StringToUint64(input_string, &output));
- EXPECT_EQ(6U, output);
-
- string16 utf16_input = UTF8ToUTF16(input_string);
- output = 0;
- EXPECT_FALSE(StringToUint64(utf16_input, &output));
- EXPECT_EQ(6U, output);
-}
-
-TEST(StringNumberConversionsTest, StringToSizeT) {
- size_t size_t_max = std::numeric_limits<size_t>::max();
- std::string size_t_max_string = StringPrintf("%" PRIuS, size_t_max);
-
- static const struct {
- std::string input;
- size_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 42, true},
- {"-2147483648", 0, false},
- {"2147483647", INT_MAX, true},
- {"-2147483649", 0, false},
- {"-99999999999", 0, false},
- {"2147483648", 2147483648U, true},
-#if SIZE_MAX > 4294967295U
- {"99999999999", 99999999999U, true},
-#endif
- {"-9223372036854775808", 0, false},
- {"09", 9, true},
- {"-09", 0, false},
- {"", 0, false},
- {" 42", 42, false},
- {"42 ", 42, false},
- {"0x42", 0, false},
- {"\t\n\v\f\r 42", 42, false},
- {"blah42", 0, false},
- {"42blah", 42, false},
- {"blah42blah", 0, false},
- {"-273.15", 0, false},
- {"+98.6", 98, false},
- {"--123", 0, false},
- {"++123", 0, false},
- {"-+123", 0, false},
- {"+-123", 0, false},
- {"-", 0, false},
- {"-9223372036854775809", 0, false},
- {"-99999999999999999999", 0, false},
- {"999999999999999999999999", size_t_max, false},
- {size_t_max_string, size_t_max, true},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- size_t output = 0;
- EXPECT_EQ(cases[i].success, StringToSizeT(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
-
- string16 utf16_input = UTF8ToUTF16(cases[i].input);
- output = 0;
- EXPECT_EQ(cases[i].success, StringToSizeT(utf16_input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
-
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "6\06";
- std::string input_string(input, arraysize(input) - 1);
- size_t output;
- EXPECT_FALSE(StringToSizeT(input_string, &output));
- EXPECT_EQ(6U, output);
-
- string16 utf16_input = UTF8ToUTF16(input_string);
- output = 0;
- EXPECT_FALSE(StringToSizeT(utf16_input, &output));
- EXPECT_EQ(6U, output);
-}
-
-TEST(StringNumberConversionsTest, HexStringToInt) {
- static const struct {
- std::string input;
- int64_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 66, true},
- {"-42", -66, true},
- {"+42", 66, true},
- {"7fffffff", INT_MAX, true},
- {"-80000000", INT_MIN, true},
- {"80000000", INT_MAX, false}, // Overflow test.
- {"-80000001", INT_MIN, false}, // Underflow test.
- {"0x42", 66, true},
- {"-0x42", -66, true},
- {"+0x42", 66, true},
- {"0x7fffffff", INT_MAX, true},
- {"-0x80000000", INT_MIN, true},
- {"-80000000", INT_MIN, true},
- {"80000000", INT_MAX, false}, // Overflow test.
- {"-80000001", INT_MIN, false}, // Underflow test.
- {"0x0f", 15, true},
- {"0f", 15, true},
- {" 45", 0x45, false},
- {"\t\n\v\f\r 0x45", 0x45, false},
- {" 45", 0x45, false},
- {"45 ", 0x45, false},
- {"45:", 0x45, false},
- {"efgh", 0xef, false},
- {"0xefgh", 0xef, false},
- {"hgfe", 0, false},
- {"-", 0, false},
- {"", 0, false},
- {"0x", 0, false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- int output = 0;
- EXPECT_EQ(cases[i].success, HexStringToInt(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "0xc0ffee\0" "9";
- std::string input_string(input, arraysize(input) - 1);
- int output;
- EXPECT_FALSE(HexStringToInt(input_string, &output));
- EXPECT_EQ(0xc0ffee, output);
-}
-
-TEST(StringNumberConversionsTest, HexStringToUInt) {
- static const struct {
- std::string input;
- uint32_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 0x42, true},
- {"-42", 0, false},
- {"+42", 0x42, true},
- {"7fffffff", INT_MAX, true},
- {"-80000000", 0, false},
- {"ffffffff", 0xffffffff, true},
- {"DeadBeef", 0xdeadbeef, true},
- {"0x42", 0x42, true},
- {"-0x42", 0, false},
- {"+0x42", 0x42, true},
- {"0x7fffffff", INT_MAX, true},
- {"-0x80000000", 0, false},
- {"0xffffffff", std::numeric_limits<uint32_t>::max(), true},
- {"0XDeadBeef", 0xdeadbeef, true},
- {"0x7fffffffffffffff", std::numeric_limits<uint32_t>::max(),
- false}, // Overflow test.
- {"-0x8000000000000000", 0, false},
- {"0x8000000000000000", std::numeric_limits<uint32_t>::max(),
- false}, // Overflow test.
- {"-0x8000000000000001", 0, false},
- {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
- false}, // Overflow test.
- {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
- false}, // Overflow test.
- {"0x0000000000000000", 0, true},
- {"0000000000000000", 0, true},
- {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint32_t>::max(),
- false}, // Overflow test.
- {"0x0f", 0x0f, true},
- {"0f", 0x0f, true},
- {" 45", 0x45, false},
- {"\t\n\v\f\r 0x45", 0x45, false},
- {" 45", 0x45, false},
- {"45 ", 0x45, false},
- {"45:", 0x45, false},
- {"efgh", 0xef, false},
- {"0xefgh", 0xef, false},
- {"hgfe", 0, false},
- {"-", 0, false},
- {"", 0, false},
- {"0x", 0, false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- uint32_t output = 0;
- EXPECT_EQ(cases[i].success, HexStringToUInt(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "0xc0ffee\0" "9";
- std::string input_string(input, arraysize(input) - 1);
- uint32_t output;
- EXPECT_FALSE(HexStringToUInt(input_string, &output));
- EXPECT_EQ(0xc0ffeeU, output);
-}
-
-TEST(StringNumberConversionsTest, HexStringToInt64) {
- static const struct {
- std::string input;
- int64_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 66, true},
- {"-42", -66, true},
- {"+42", 66, true},
- {"40acd88557b", INT64_C(4444444448123), true},
- {"7fffffff", INT_MAX, true},
- {"-80000000", INT_MIN, true},
- {"ffffffff", 0xffffffff, true},
- {"DeadBeef", 0xdeadbeef, true},
- {"0x42", 66, true},
- {"-0x42", -66, true},
- {"+0x42", 66, true},
- {"0x40acd88557b", INT64_C(4444444448123), true},
- {"0x7fffffff", INT_MAX, true},
- {"-0x80000000", INT_MIN, true},
- {"0xffffffff", 0xffffffff, true},
- {"0XDeadBeef", 0xdeadbeef, true},
- {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
- {"-0x8000000000000000", std::numeric_limits<int64_t>::min(), true},
- {"0x8000000000000000", std::numeric_limits<int64_t>::max(),
- false}, // Overflow test.
- {"-0x8000000000000001", std::numeric_limits<int64_t>::min(),
- false}, // Underflow test.
- {"0x0f", 15, true},
- {"0f", 15, true},
- {" 45", 0x45, false},
- {"\t\n\v\f\r 0x45", 0x45, false},
- {" 45", 0x45, false},
- {"45 ", 0x45, false},
- {"45:", 0x45, false},
- {"efgh", 0xef, false},
- {"0xefgh", 0xef, false},
- {"hgfe", 0, false},
- {"-", 0, false},
- {"", 0, false},
- {"0x", 0, false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- int64_t output = 0;
- EXPECT_EQ(cases[i].success, HexStringToInt64(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "0xc0ffee\0" "9";
- std::string input_string(input, arraysize(input) - 1);
- int64_t output;
- EXPECT_FALSE(HexStringToInt64(input_string, &output));
- EXPECT_EQ(0xc0ffee, output);
-}
-
-TEST(StringNumberConversionsTest, HexStringToUInt64) {
- static const struct {
- std::string input;
- uint64_t output;
- bool success;
- } cases[] = {
- {"0", 0, true},
- {"42", 66, true},
- {"-42", 0, false},
- {"+42", 66, true},
- {"40acd88557b", INT64_C(4444444448123), true},
- {"7fffffff", INT_MAX, true},
- {"-80000000", 0, false},
- {"ffffffff", 0xffffffff, true},
- {"DeadBeef", 0xdeadbeef, true},
- {"0x42", 66, true},
- {"-0x42", 0, false},
- {"+0x42", 66, true},
- {"0x40acd88557b", INT64_C(4444444448123), true},
- {"0x7fffffff", INT_MAX, true},
- {"-0x80000000", 0, false},
- {"0xffffffff", 0xffffffff, true},
- {"0XDeadBeef", 0xdeadbeef, true},
- {"0x7fffffffffffffff", std::numeric_limits<int64_t>::max(), true},
- {"-0x8000000000000000", 0, false},
- {"0x8000000000000000", UINT64_C(0x8000000000000000), true},
- {"-0x8000000000000001", 0, false},
- {"0xFFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
- {"FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(), true},
- {"0x0000000000000000", 0, true},
- {"0000000000000000", 0, true},
- {"1FFFFFFFFFFFFFFFF", std::numeric_limits<uint64_t>::max(),
- false}, // Overflow test.
- {"0x0f", 15, true},
- {"0f", 15, true},
- {" 45", 0x45, false},
- {"\t\n\v\f\r 0x45", 0x45, false},
- {" 45", 0x45, false},
- {"45 ", 0x45, false},
- {"45:", 0x45, false},
- {"efgh", 0xef, false},
- {"0xefgh", 0xef, false},
- {"hgfe", 0, false},
- {"-", 0, false},
- {"", 0, false},
- {"0x", 0, false},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- uint64_t output = 0;
- EXPECT_EQ(cases[i].success, HexStringToUInt64(cases[i].input, &output));
- EXPECT_EQ(cases[i].output, output);
- }
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "0xc0ffee\0" "9";
- std::string input_string(input, arraysize(input) - 1);
- uint64_t output;
- EXPECT_FALSE(HexStringToUInt64(input_string, &output));
- EXPECT_EQ(0xc0ffeeU, output);
-}
-
-TEST(StringNumberConversionsTest, HexStringToBytes) {
- static const struct {
- const std::string input;
- const char* output;
- size_t output_len;
- bool success;
- } cases[] = {
- {"0", "", 0, false}, // odd number of characters fails
- {"00", "\0", 1, true},
- {"42", "\x42", 1, true},
- {"-42", "", 0, false}, // any non-hex value fails
- {"+42", "", 0, false},
- {"7fffffff", "\x7f\xff\xff\xff", 4, true},
- {"80000000", "\x80\0\0\0", 4, true},
- {"deadbeef", "\xde\xad\xbe\xef", 4, true},
- {"DeadBeef", "\xde\xad\xbe\xef", 4, true},
- {"0x42", "", 0, false}, // leading 0x fails (x is not hex)
- {"0f", "\xf", 1, true},
- {"45 ", "\x45", 1, false},
- {"efgh", "\xef", 1, false},
- {"", "", 0, false},
- {"0123456789ABCDEF", "\x01\x23\x45\x67\x89\xAB\xCD\xEF", 8, true},
- {"0123456789ABCDEF012345",
- "\x01\x23\x45\x67\x89\xAB\xCD\xEF\x01\x23\x45", 11, true},
- };
-
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- std::vector<uint8_t> output;
- std::vector<uint8_t> compare;
- EXPECT_EQ(cases[i].success, HexStringToBytes(cases[i].input, &output)) <<
- i << ": " << cases[i].input;
- for (size_t j = 0; j < cases[i].output_len; ++j)
- compare.push_back(static_cast<uint8_t>(cases[i].output[j]));
- ASSERT_EQ(output.size(), compare.size()) << i << ": " << cases[i].input;
- EXPECT_TRUE(std::equal(output.begin(), output.end(), compare.begin())) <<
- i << ": " << cases[i].input;
- }
-}
-
-TEST(StringNumberConversionsTest, StringToDouble) {
- static const struct {
- std::string input;
- double output;
- bool success;
- } cases[] = {
- // Test different forms of zero.
- {"0", 0.0, true},
- {"+0", 0.0, true},
- {"-0", 0.0, true},
- {"0.0", 0.0, true},
- {"000000000000000000000000000000.0", 0.0, true},
- {"0.000000000000000000000000000", 0.0, true},
-
- // Test the answer.
- {"42", 42.0, true},
- {"-42", -42.0, true},
-
- // Test variances of an ordinary number.
- {"123.45", 123.45, true},
- {"-123.45", -123.45, true},
- {"+123.45", 123.45, true},
-
- // Test different forms of representation.
- {"2.99792458e8", 299792458.0, true},
- {"149597870.691E+3", 149597870691.0, true},
- {"6.", 6.0, true},
-
- // Test around the largest/smallest value that a double can represent.
- {"9e307", 9e307, true},
- {"1.7976e308", 1.7976e308, true},
- {"1.7977e308", HUGE_VAL, false},
- {"1.797693134862315807e+308", HUGE_VAL, true},
- {"1.797693134862315808e+308", HUGE_VAL, false},
- {"9e308", HUGE_VAL, false},
- {"9e309", HUGE_VAL, false},
- {"9e999", HUGE_VAL, false},
- {"9e1999", HUGE_VAL, false},
- {"9e19999", HUGE_VAL, false},
- {"9e99999999999999999999", HUGE_VAL, false},
- {"-9e307", -9e307, true},
- {"-1.7976e308", -1.7976e308, true},
- {"-1.7977e308", -HUGE_VAL, false},
- {"-1.797693134862315807e+308", -HUGE_VAL, true},
- {"-1.797693134862315808e+308", -HUGE_VAL, false},
- {"-9e308", -HUGE_VAL, false},
- {"-9e309", -HUGE_VAL, false},
- {"-9e999", -HUGE_VAL, false},
- {"-9e1999", -HUGE_VAL, false},
- {"-9e19999", -HUGE_VAL, false},
- {"-9e99999999999999999999", -HUGE_VAL, false},
-
- // Test more exponents.
- {"1e-2", 0.01, true},
- {"42 ", 42.0, false},
- {" 1e-2", 0.01, false},
- {"1e-2 ", 0.01, false},
- {"-1E-7", -0.0000001, true},
- {"01e02", 100, true},
- {"2.3e15", 2.3e15, true},
- {"100e-309", 100e-309, true},
-
- // Test some invalid cases.
- {"\t\n\v\f\r -123.45e2", -12345.0, false},
- {"+123 e4", 123.0, false},
- {"123e ", 123.0, false},
- {"123e", 123.0, false},
- {" 2.99", 2.99, false},
- {"1e3.4", 1000.0, false},
- {"nothing", 0.0, false},
- {"-", 0.0, false},
- {"+", 0.0, false},
- {"", 0.0, false},
-
- // crbug.org/588726
- {"-0.0010000000000000000000000000000000000000001e-256",
- -1.0000000000000001e-259, true},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- double output;
- errno = 1;
- EXPECT_EQ(cases[i].success, StringToDouble(cases[i].input, &output));
- if (cases[i].success)
- EXPECT_EQ(1, errno) << i; // confirm that errno is unchanged.
- EXPECT_DOUBLE_EQ(cases[i].output, output);
- }
-
- // One additional test to verify that conversion of numbers in strings with
- // embedded NUL characters. The NUL and extra data after it should be
- // interpreted as junk after the number.
- const char input[] = "3.14\0" "159";
- std::string input_string(input, arraysize(input) - 1);
- double output;
- EXPECT_FALSE(StringToDouble(input_string, &output));
- EXPECT_DOUBLE_EQ(3.14, output);
-}
-
-TEST(StringNumberConversionsTest, DoubleToString) {
- static const struct {
- double input;
- const char* expected;
- } cases[] = {
- {0.0, "0"},
- {1.25, "1.25"},
- {1.33518e+012, "1.33518e+12"},
- {1.33489e+012, "1.33489e+12"},
- {1.33505e+012, "1.33505e+12"},
- {1.33545e+009, "1335450000"},
- {1.33503e+009, "1335030000"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- EXPECT_EQ(cases[i].expected, NumberToString(cases[i].input));
- EXPECT_EQ(cases[i].expected, UTF16ToUTF8(NumberToString16(cases[i].input)));
- }
-
- // The following two values were seen in crashes in the wild.
- const char input_bytes[8] = {0, 0, 0, 0, '\xee', '\x6d', '\x73', '\x42'};
- double input = 0;
- memcpy(&input, input_bytes, arraysize(input_bytes));
- EXPECT_EQ("1335179083776", NumberToString(input));
- const char input_bytes2[8] =
- {0, 0, 0, '\xa0', '\xda', '\x6c', '\x73', '\x42'};
- input = 0;
- memcpy(&input, input_bytes2, arraysize(input_bytes2));
- EXPECT_EQ("1334890332160", NumberToString(input));
-}
-
-TEST(StringNumberConversionsTest, HexEncode) {
- std::string hex(HexEncode(nullptr, 0));
- EXPECT_EQ(hex.length(), 0U);
- unsigned char bytes[] = {0x01, 0xff, 0x02, 0xfe, 0x03, 0x80, 0x81};
- hex = HexEncode(bytes, sizeof(bytes));
- EXPECT_EQ(hex.compare("01FF02FE038081"), 0);
-}
-
-// Test cases of known-bad strtod conversions that motivated the use of dmg_fp.
-// See https://bugs.chromium.org/p/chromium/issues/detail?id=593512.
-TEST(StringNumberConversionsTest, StrtodFailures) {
- static const struct {
- const char* input;
- uint64_t expected;
- } cases[] = {
- // http://www.exploringbinary.com/incorrectly-rounded-conversions-in-visual-c-plus-plus/
- {"9214843084008499", 0x43405e6cec57761aULL},
- {"0.500000000000000166533453693773481063544750213623046875",
- 0x3fe0000000000002ULL},
- {"30078505129381147446200", 0x44997a3c7271b021ULL},
- {"1777820000000000000001", 0x4458180d5bad2e3eULL},
- {"0.500000000000000166547006220929549868969843373633921146392822265625",
- 0x3fe0000000000002ULL},
- {"0.50000000000000016656055874808561867439493653364479541778564453125",
- 0x3fe0000000000002ULL},
- {"0.3932922657273", 0x3fd92bb352c4623aULL},
-
- // http://www.exploringbinary.com/incorrectly-rounded-conversions-in-gcc-and-glibc/
- {"0.500000000000000166533453693773481063544750213623046875",
- 0x3fe0000000000002ULL},
- {"3.518437208883201171875e13", 0x42c0000000000002ULL},
- {"62.5364939768271845828", 0x404f44abd5aa7ca4ULL},
- {"8.10109172351e-10", 0x3e0bd5cbaef0fd0cULL},
- {"1.50000000000000011102230246251565404236316680908203125",
- 0x3ff8000000000000ULL},
- {"9007199254740991.4999999999999999999999999999999995",
- 0x433fffffffffffffULL},
-
- // http://www.exploringbinary.com/incorrect-decimal-to-floating-point-conversion-in-sqlite/
- {"1e-23", 0x3b282db34012b251ULL},
- {"8.533e+68", 0x4e3fa69165a8eea2ULL},
- {"4.1006e-184", 0x19dbe0d1c7ea60c9ULL},
- {"9.998e+307", 0x7fe1cc0a350ca87bULL},
- {"9.9538452227e-280", 0x0602117ae45cde43ULL},
- {"6.47660115e-260", 0x0a1fdd9e333badadULL},
- {"7.4e+47", 0x49e033d7eca0adefULL},
- {"5.92e+48", 0x4a1033d7eca0adefULL},
- {"7.35e+66", 0x4dd172b70eababa9ULL},
- {"8.32116e+55", 0x4b8b2628393e02cdULL},
- };
-
- for (const auto& test : cases) {
- double output;
- EXPECT_TRUE(StringToDouble(test.input, &output));
- EXPECT_EQ(bit_cast<uint64_t>(output), test.expected);
- }
-}
-
-} // namespace base
diff --git a/base/strings/string_piece_unittest.cc b/base/strings/string_piece_unittest.cc
deleted file mode 100644
index 17d0897..0000000
--- a/base/strings/string_piece_unittest.cc
+++ /dev/null
@@ -1,805 +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 <string>
-
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-template <typename T>
-class CommonStringPieceTest : public ::testing::Test {
- public:
- static const T as_string(const char* input) {
- return T(input);
- }
- static const T& as_string(const T& input) {
- return input;
- }
-};
-
-template <>
-class CommonStringPieceTest<string16> : public ::testing::Test {
- public:
- static const string16 as_string(const char* input) {
- return ASCIIToUTF16(input);
- }
- static const string16 as_string(const std::string& input) {
- return ASCIIToUTF16(input);
- }
-};
-
-typedef ::testing::Types<std::string, string16> SupportedStringTypes;
-
-TYPED_TEST_CASE(CommonStringPieceTest, SupportedStringTypes);
-
-TYPED_TEST(CommonStringPieceTest, CheckComparisonOperators) {
-#define CMP_Y(op, x, y) \
- { \
- TypeParam lhs(TestFixture::as_string(x)); \
- TypeParam rhs(TestFixture::as_string(y)); \
- ASSERT_TRUE( (BasicStringPiece<TypeParam>((lhs.c_str())) op \
- BasicStringPiece<TypeParam>((rhs.c_str())))); \
- ASSERT_TRUE( (BasicStringPiece<TypeParam>((lhs.c_str())).compare( \
- BasicStringPiece<TypeParam>((rhs.c_str()))) op 0)); \
- }
-
-#define CMP_N(op, x, y) \
- { \
- TypeParam lhs(TestFixture::as_string(x)); \
- TypeParam rhs(TestFixture::as_string(y)); \
- ASSERT_FALSE( (BasicStringPiece<TypeParam>((lhs.c_str())) op \
- BasicStringPiece<TypeParam>((rhs.c_str())))); \
- ASSERT_FALSE( (BasicStringPiece<TypeParam>((lhs.c_str())).compare( \
- BasicStringPiece<TypeParam>((rhs.c_str()))) op 0)); \
- }
-
- CMP_Y(==, "", "");
- CMP_Y(==, "a", "a");
- CMP_Y(==, "aa", "aa");
- CMP_N(==, "a", "");
- CMP_N(==, "", "a");
- CMP_N(==, "a", "b");
- CMP_N(==, "a", "aa");
- CMP_N(==, "aa", "a");
-
- CMP_N(!=, "", "");
- CMP_N(!=, "a", "a");
- CMP_N(!=, "aa", "aa");
- CMP_Y(!=, "a", "");
- CMP_Y(!=, "", "a");
- CMP_Y(!=, "a", "b");
- CMP_Y(!=, "a", "aa");
- CMP_Y(!=, "aa", "a");
-
- CMP_Y(<, "a", "b");
- CMP_Y(<, "a", "aa");
- CMP_Y(<, "aa", "b");
- CMP_Y(<, "aa", "bb");
- CMP_N(<, "a", "a");
- CMP_N(<, "b", "a");
- CMP_N(<, "aa", "a");
- CMP_N(<, "b", "aa");
- CMP_N(<, "bb", "aa");
-
- CMP_Y(<=, "a", "a");
- CMP_Y(<=, "a", "b");
- CMP_Y(<=, "a", "aa");
- CMP_Y(<=, "aa", "b");
- CMP_Y(<=, "aa", "bb");
- CMP_N(<=, "b", "a");
- CMP_N(<=, "aa", "a");
- CMP_N(<=, "b", "aa");
- CMP_N(<=, "bb", "aa");
-
- CMP_N(>=, "a", "b");
- CMP_N(>=, "a", "aa");
- CMP_N(>=, "aa", "b");
- CMP_N(>=, "aa", "bb");
- CMP_Y(>=, "a", "a");
- CMP_Y(>=, "b", "a");
- CMP_Y(>=, "aa", "a");
- CMP_Y(>=, "b", "aa");
- CMP_Y(>=, "bb", "aa");
-
- CMP_N(>, "a", "a");
- CMP_N(>, "a", "b");
- CMP_N(>, "a", "aa");
- CMP_N(>, "aa", "b");
- CMP_N(>, "aa", "bb");
- CMP_Y(>, "b", "a");
- CMP_Y(>, "aa", "a");
- CMP_Y(>, "b", "aa");
- CMP_Y(>, "bb", "aa");
-
- std::string x;
- for (int i = 0; i < 256; i++) {
- x += 'a';
- std::string y = x;
- CMP_Y(==, x, y);
- for (int j = 0; j < i; j++) {
- std::string z = x;
- z[j] = 'b'; // Differs in position 'j'
- CMP_N(==, x, z);
- }
- }
-
-#undef CMP_Y
-#undef CMP_N
-}
-
-TYPED_TEST(CommonStringPieceTest, CheckSTL) {
- TypeParam alphabet(TestFixture::as_string("abcdefghijklmnopqrstuvwxyz"));
- TypeParam abc(TestFixture::as_string("abc"));
- TypeParam xyz(TestFixture::as_string("xyz"));
- TypeParam foobar(TestFixture::as_string("foobar"));
-
- BasicStringPiece<TypeParam> a(alphabet);
- BasicStringPiece<TypeParam> b(abc);
- BasicStringPiece<TypeParam> c(xyz);
- BasicStringPiece<TypeParam> d(foobar);
- BasicStringPiece<TypeParam> e;
- TypeParam temp(TestFixture::as_string("123"));
- temp += static_cast<typename TypeParam::value_type>(0);
- temp += TestFixture::as_string("456");
- BasicStringPiece<TypeParam> f(temp);
-
- ASSERT_EQ(a[6], static_cast<typename TypeParam::value_type>('g'));
- ASSERT_EQ(b[0], static_cast<typename TypeParam::value_type>('a'));
- ASSERT_EQ(c[2], static_cast<typename TypeParam::value_type>('z'));
- ASSERT_EQ(f[3], static_cast<typename TypeParam::value_type>('\0'));
- ASSERT_EQ(f[5], static_cast<typename TypeParam::value_type>('5'));
-
- ASSERT_EQ(*d.data(), static_cast<typename TypeParam::value_type>('f'));
- ASSERT_EQ(d.data()[5], static_cast<typename TypeParam::value_type>('r'));
- ASSERT_EQ(e.data(), nullptr);
-
- ASSERT_EQ(*a.begin(), static_cast<typename TypeParam::value_type>('a'));
- ASSERT_EQ(*(b.begin() + 2), static_cast<typename TypeParam::value_type>('c'));
- ASSERT_EQ(*(c.end() - 1), static_cast<typename TypeParam::value_type>('z'));
-
- ASSERT_EQ(*a.rbegin(), static_cast<typename TypeParam::value_type>('z'));
- ASSERT_EQ(*(b.rbegin() + 2),
- static_cast<typename TypeParam::value_type>('a'));
- ASSERT_EQ(*(c.rend() - 1), static_cast<typename TypeParam::value_type>('x'));
- ASSERT_EQ(a.rbegin() + 26, a.rend());
-
- ASSERT_EQ(a.size(), 26U);
- ASSERT_EQ(b.size(), 3U);
- ASSERT_EQ(c.size(), 3U);
- ASSERT_EQ(d.size(), 6U);
- ASSERT_EQ(e.size(), 0U);
- ASSERT_EQ(f.size(), 7U);
-
- ASSERT_TRUE(!d.empty());
- ASSERT_TRUE(d.begin() != d.end());
- ASSERT_EQ(d.begin() + 6, d.end());
-
- ASSERT_TRUE(e.empty());
- ASSERT_EQ(e.begin(), e.end());
-
- d.clear();
- ASSERT_EQ(d.size(), 0U);
- ASSERT_TRUE(d.empty());
- ASSERT_EQ(d.data(), nullptr);
- ASSERT_EQ(d.begin(), d.end());
-
- ASSERT_GE(a.max_size(), a.capacity());
- ASSERT_GE(a.capacity(), a.size());
-}
-
-TYPED_TEST(CommonStringPieceTest, CheckFind) {
- typedef BasicStringPiece<TypeParam> Piece;
-
- TypeParam alphabet(TestFixture::as_string("abcdefghijklmnopqrstuvwxyz"));
- TypeParam abc(TestFixture::as_string("abc"));
- TypeParam xyz(TestFixture::as_string("xyz"));
- TypeParam foobar(TestFixture::as_string("foobar"));
-
- BasicStringPiece<TypeParam> a(alphabet);
- BasicStringPiece<TypeParam> b(abc);
- BasicStringPiece<TypeParam> c(xyz);
- BasicStringPiece<TypeParam> d(foobar);
-
- d.clear();
- Piece e;
- TypeParam temp(TestFixture::as_string("123"));
- temp.push_back('\0');
- temp += TestFixture::as_string("456");
- Piece f(temp);
-
- typename TypeParam::value_type buf[4] = { '%', '%', '%', '%' };
- ASSERT_EQ(a.copy(buf, 4), 4U);
- ASSERT_EQ(buf[0], a[0]);
- ASSERT_EQ(buf[1], a[1]);
- ASSERT_EQ(buf[2], a[2]);
- ASSERT_EQ(buf[3], a[3]);
- ASSERT_EQ(a.copy(buf, 3, 7), 3U);
- ASSERT_EQ(buf[0], a[7]);
- ASSERT_EQ(buf[1], a[8]);
- ASSERT_EQ(buf[2], a[9]);
- ASSERT_EQ(buf[3], a[3]);
- ASSERT_EQ(c.copy(buf, 99), 3U);
- ASSERT_EQ(buf[0], c[0]);
- ASSERT_EQ(buf[1], c[1]);
- ASSERT_EQ(buf[2], c[2]);
- ASSERT_EQ(buf[3], a[3]);
-
- ASSERT_EQ(Piece::npos, TypeParam::npos);
-
- ASSERT_EQ(a.find(b), 0U);
- ASSERT_EQ(a.find(b, 1), Piece::npos);
- ASSERT_EQ(a.find(c), 23U);
- ASSERT_EQ(a.find(c, 9), 23U);
- ASSERT_EQ(a.find(c, Piece::npos), Piece::npos);
- ASSERT_EQ(b.find(c), Piece::npos);
- ASSERT_EQ(b.find(c, Piece::npos), Piece::npos);
- ASSERT_EQ(a.find(d), 0U);
- ASSERT_EQ(a.find(e), 0U);
- ASSERT_EQ(a.find(d, 12), 12U);
- ASSERT_EQ(a.find(e, 17), 17U);
- TypeParam not_found(TestFixture::as_string("xx not found bb"));
- Piece g(not_found);
- ASSERT_EQ(a.find(g), Piece::npos);
- // empty string nonsense
- ASSERT_EQ(d.find(b), Piece::npos);
- ASSERT_EQ(e.find(b), Piece::npos);
- ASSERT_EQ(d.find(b, 4), Piece::npos);
- ASSERT_EQ(e.find(b, 7), Piece::npos);
-
- size_t empty_search_pos = TypeParam().find(TypeParam());
- ASSERT_EQ(d.find(d), empty_search_pos);
- ASSERT_EQ(d.find(e), empty_search_pos);
- ASSERT_EQ(e.find(d), empty_search_pos);
- ASSERT_EQ(e.find(e), empty_search_pos);
- ASSERT_EQ(d.find(d, 4), std::string().find(std::string(), 4));
- ASSERT_EQ(d.find(e, 4), std::string().find(std::string(), 4));
- ASSERT_EQ(e.find(d, 4), std::string().find(std::string(), 4));
- ASSERT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
-
- ASSERT_EQ(a.find('a'), 0U);
- ASSERT_EQ(a.find('c'), 2U);
- ASSERT_EQ(a.find('z'), 25U);
- ASSERT_EQ(a.find('$'), Piece::npos);
- ASSERT_EQ(a.find('\0'), Piece::npos);
- ASSERT_EQ(f.find('\0'), 3U);
- ASSERT_EQ(f.find('3'), 2U);
- ASSERT_EQ(f.find('5'), 5U);
- ASSERT_EQ(g.find('o'), 4U);
- ASSERT_EQ(g.find('o', 4), 4U);
- ASSERT_EQ(g.find('o', 5), 8U);
- ASSERT_EQ(a.find('b', 5), Piece::npos);
- // empty string nonsense
- ASSERT_EQ(d.find('\0'), Piece::npos);
- ASSERT_EQ(e.find('\0'), Piece::npos);
- ASSERT_EQ(d.find('\0', 4), Piece::npos);
- ASSERT_EQ(e.find('\0', 7), Piece::npos);
- ASSERT_EQ(d.find('x'), Piece::npos);
- ASSERT_EQ(e.find('x'), Piece::npos);
- ASSERT_EQ(d.find('x', 4), Piece::npos);
- ASSERT_EQ(e.find('x', 7), Piece::npos);
-
- ASSERT_EQ(a.rfind(b), 0U);
- ASSERT_EQ(a.rfind(b, 1), 0U);
- ASSERT_EQ(a.rfind(c), 23U);
- ASSERT_EQ(a.rfind(c, 22U), Piece::npos);
- ASSERT_EQ(a.rfind(c, 1U), Piece::npos);
- ASSERT_EQ(a.rfind(c, 0U), Piece::npos);
- ASSERT_EQ(b.rfind(c), Piece::npos);
- ASSERT_EQ(b.rfind(c, 0U), Piece::npos);
- ASSERT_EQ(a.rfind(d), static_cast<size_t>(a.as_string().rfind(TypeParam())));
- ASSERT_EQ(a.rfind(e), a.as_string().rfind(TypeParam()));
- ASSERT_EQ(a.rfind(d), static_cast<size_t>(TypeParam(a).rfind(TypeParam())));
- ASSERT_EQ(a.rfind(e), TypeParam(a).rfind(TypeParam()));
- ASSERT_EQ(a.rfind(d, 12), 12U);
- ASSERT_EQ(a.rfind(e, 17), 17U);
- ASSERT_EQ(a.rfind(g), Piece::npos);
- ASSERT_EQ(d.rfind(b), Piece::npos);
- ASSERT_EQ(e.rfind(b), Piece::npos);
- ASSERT_EQ(d.rfind(b, 4), Piece::npos);
- ASSERT_EQ(e.rfind(b, 7), Piece::npos);
- // empty string nonsense
- ASSERT_EQ(d.rfind(d, 4), std::string().rfind(std::string()));
- ASSERT_EQ(e.rfind(d, 7), std::string().rfind(std::string()));
- ASSERT_EQ(d.rfind(e, 4), std::string().rfind(std::string()));
- ASSERT_EQ(e.rfind(e, 7), std::string().rfind(std::string()));
- ASSERT_EQ(d.rfind(d), std::string().rfind(std::string()));
- ASSERT_EQ(e.rfind(d), std::string().rfind(std::string()));
- ASSERT_EQ(d.rfind(e), std::string().rfind(std::string()));
- ASSERT_EQ(e.rfind(e), std::string().rfind(std::string()));
-
- ASSERT_EQ(g.rfind('o'), 8U);
- ASSERT_EQ(g.rfind('q'), Piece::npos);
- ASSERT_EQ(g.rfind('o', 8), 8U);
- ASSERT_EQ(g.rfind('o', 7), 4U);
- ASSERT_EQ(g.rfind('o', 3), Piece::npos);
- ASSERT_EQ(f.rfind('\0'), 3U);
- ASSERT_EQ(f.rfind('\0', 12), 3U);
- ASSERT_EQ(f.rfind('3'), 2U);
- ASSERT_EQ(f.rfind('5'), 5U);
- // empty string nonsense
- ASSERT_EQ(d.rfind('o'), Piece::npos);
- ASSERT_EQ(e.rfind('o'), Piece::npos);
- ASSERT_EQ(d.rfind('o', 4), Piece::npos);
- ASSERT_EQ(e.rfind('o', 7), Piece::npos);
-
- TypeParam one_two_three_four(TestFixture::as_string("one,two:three;four"));
- TypeParam comma_colon(TestFixture::as_string(",:"));
- ASSERT_EQ(3U, Piece(one_two_three_four).find_first_of(comma_colon));
- ASSERT_EQ(a.find_first_of(b), 0U);
- ASSERT_EQ(a.find_first_of(b, 0), 0U);
- ASSERT_EQ(a.find_first_of(b, 1), 1U);
- ASSERT_EQ(a.find_first_of(b, 2), 2U);
- ASSERT_EQ(a.find_first_of(b, 3), Piece::npos);
- ASSERT_EQ(a.find_first_of(c), 23U);
- ASSERT_EQ(a.find_first_of(c, 23), 23U);
- ASSERT_EQ(a.find_first_of(c, 24), 24U);
- ASSERT_EQ(a.find_first_of(c, 25), 25U);
- ASSERT_EQ(a.find_first_of(c, 26), Piece::npos);
- ASSERT_EQ(g.find_first_of(b), 13U);
- ASSERT_EQ(g.find_first_of(c), 0U);
- ASSERT_EQ(a.find_first_of(f), Piece::npos);
- ASSERT_EQ(f.find_first_of(a), Piece::npos);
- // empty string nonsense
- ASSERT_EQ(a.find_first_of(d), Piece::npos);
- ASSERT_EQ(a.find_first_of(e), Piece::npos);
- ASSERT_EQ(d.find_first_of(b), Piece::npos);
- ASSERT_EQ(e.find_first_of(b), Piece::npos);
- ASSERT_EQ(d.find_first_of(d), Piece::npos);
- ASSERT_EQ(e.find_first_of(d), Piece::npos);
- ASSERT_EQ(d.find_first_of(e), Piece::npos);
- ASSERT_EQ(e.find_first_of(e), Piece::npos);
-
- ASSERT_EQ(a.find_first_not_of(b), 3U);
- ASSERT_EQ(a.find_first_not_of(c), 0U);
- ASSERT_EQ(b.find_first_not_of(a), Piece::npos);
- ASSERT_EQ(c.find_first_not_of(a), Piece::npos);
- ASSERT_EQ(f.find_first_not_of(a), 0U);
- ASSERT_EQ(a.find_first_not_of(f), 0U);
- ASSERT_EQ(a.find_first_not_of(d), 0U);
- ASSERT_EQ(a.find_first_not_of(e), 0U);
- // empty string nonsense
- ASSERT_EQ(d.find_first_not_of(a), Piece::npos);
- ASSERT_EQ(e.find_first_not_of(a), Piece::npos);
- ASSERT_EQ(d.find_first_not_of(d), Piece::npos);
- ASSERT_EQ(e.find_first_not_of(d), Piece::npos);
- ASSERT_EQ(d.find_first_not_of(e), Piece::npos);
- ASSERT_EQ(e.find_first_not_of(e), Piece::npos);
-
- TypeParam equals(TestFixture::as_string("===="));
- Piece h(equals);
- ASSERT_EQ(h.find_first_not_of('='), Piece::npos);
- ASSERT_EQ(h.find_first_not_of('=', 3), Piece::npos);
- ASSERT_EQ(h.find_first_not_of('\0'), 0U);
- ASSERT_EQ(g.find_first_not_of('x'), 2U);
- ASSERT_EQ(f.find_first_not_of('\0'), 0U);
- ASSERT_EQ(f.find_first_not_of('\0', 3), 4U);
- ASSERT_EQ(f.find_first_not_of('\0', 2), 2U);
- // empty string nonsense
- ASSERT_EQ(d.find_first_not_of('x'), Piece::npos);
- ASSERT_EQ(e.find_first_not_of('x'), Piece::npos);
- ASSERT_EQ(d.find_first_not_of('\0'), Piece::npos);
- ASSERT_EQ(e.find_first_not_of('\0'), Piece::npos);
-
- // Piece g("xx not found bb");
- TypeParam fifty_six(TestFixture::as_string("56"));
- Piece i(fifty_six);
- ASSERT_EQ(h.find_last_of(a), Piece::npos);
- ASSERT_EQ(g.find_last_of(a), g.size()-1);
- ASSERT_EQ(a.find_last_of(b), 2U);
- ASSERT_EQ(a.find_last_of(c), a.size()-1);
- ASSERT_EQ(f.find_last_of(i), 6U);
- ASSERT_EQ(a.find_last_of('a'), 0U);
- ASSERT_EQ(a.find_last_of('b'), 1U);
- ASSERT_EQ(a.find_last_of('z'), 25U);
- ASSERT_EQ(a.find_last_of('a', 5), 0U);
- ASSERT_EQ(a.find_last_of('b', 5), 1U);
- ASSERT_EQ(a.find_last_of('b', 0), Piece::npos);
- ASSERT_EQ(a.find_last_of('z', 25), 25U);
- ASSERT_EQ(a.find_last_of('z', 24), Piece::npos);
- ASSERT_EQ(f.find_last_of(i, 5), 5U);
- ASSERT_EQ(f.find_last_of(i, 6), 6U);
- ASSERT_EQ(f.find_last_of(a, 4), Piece::npos);
- // empty string nonsense
- ASSERT_EQ(f.find_last_of(d), Piece::npos);
- ASSERT_EQ(f.find_last_of(e), Piece::npos);
- ASSERT_EQ(f.find_last_of(d, 4), Piece::npos);
- ASSERT_EQ(f.find_last_of(e, 4), Piece::npos);
- ASSERT_EQ(d.find_last_of(d), Piece::npos);
- ASSERT_EQ(d.find_last_of(e), Piece::npos);
- ASSERT_EQ(e.find_last_of(d), Piece::npos);
- ASSERT_EQ(e.find_last_of(e), Piece::npos);
- ASSERT_EQ(d.find_last_of(f), Piece::npos);
- ASSERT_EQ(e.find_last_of(f), Piece::npos);
- ASSERT_EQ(d.find_last_of(d, 4), Piece::npos);
- ASSERT_EQ(d.find_last_of(e, 4), Piece::npos);
- ASSERT_EQ(e.find_last_of(d, 4), Piece::npos);
- ASSERT_EQ(e.find_last_of(e, 4), Piece::npos);
- ASSERT_EQ(d.find_last_of(f, 4), Piece::npos);
- ASSERT_EQ(e.find_last_of(f, 4), Piece::npos);
-
- ASSERT_EQ(a.find_last_not_of(b), a.size()-1);
- ASSERT_EQ(a.find_last_not_of(c), 22U);
- ASSERT_EQ(b.find_last_not_of(a), Piece::npos);
- ASSERT_EQ(b.find_last_not_of(b), Piece::npos);
- ASSERT_EQ(f.find_last_not_of(i), 4U);
- ASSERT_EQ(a.find_last_not_of(c, 24), 22U);
- ASSERT_EQ(a.find_last_not_of(b, 3), 3U);
- ASSERT_EQ(a.find_last_not_of(b, 2), Piece::npos);
- // empty string nonsense
- ASSERT_EQ(f.find_last_not_of(d), f.size()-1);
- ASSERT_EQ(f.find_last_not_of(e), f.size()-1);
- ASSERT_EQ(f.find_last_not_of(d, 4), 4U);
- ASSERT_EQ(f.find_last_not_of(e, 4), 4U);
- ASSERT_EQ(d.find_last_not_of(d), Piece::npos);
- ASSERT_EQ(d.find_last_not_of(e), Piece::npos);
- ASSERT_EQ(e.find_last_not_of(d), Piece::npos);
- ASSERT_EQ(e.find_last_not_of(e), Piece::npos);
- ASSERT_EQ(d.find_last_not_of(f), Piece::npos);
- ASSERT_EQ(e.find_last_not_of(f), Piece::npos);
- ASSERT_EQ(d.find_last_not_of(d, 4), Piece::npos);
- ASSERT_EQ(d.find_last_not_of(e, 4), Piece::npos);
- ASSERT_EQ(e.find_last_not_of(d, 4), Piece::npos);
- ASSERT_EQ(e.find_last_not_of(e, 4), Piece::npos);
- ASSERT_EQ(d.find_last_not_of(f, 4), Piece::npos);
- ASSERT_EQ(e.find_last_not_of(f, 4), Piece::npos);
-
- ASSERT_EQ(h.find_last_not_of('x'), h.size() - 1);
- ASSERT_EQ(h.find_last_not_of('='), Piece::npos);
- ASSERT_EQ(b.find_last_not_of('c'), 1U);
- ASSERT_EQ(h.find_last_not_of('x', 2), 2U);
- ASSERT_EQ(h.find_last_not_of('=', 2), Piece::npos);
- ASSERT_EQ(b.find_last_not_of('b', 1), 0U);
- // empty string nonsense
- ASSERT_EQ(d.find_last_not_of('x'), Piece::npos);
- ASSERT_EQ(e.find_last_not_of('x'), Piece::npos);
- ASSERT_EQ(d.find_last_not_of('\0'), Piece::npos);
- ASSERT_EQ(e.find_last_not_of('\0'), Piece::npos);
-
- ASSERT_EQ(a.substr(0, 3), b);
- ASSERT_EQ(a.substr(23), c);
- ASSERT_EQ(a.substr(23, 3), c);
- ASSERT_EQ(a.substr(23, 99), c);
- ASSERT_EQ(a.substr(0), a);
- ASSERT_EQ(a.substr(3, 2), TestFixture::as_string("de"));
- // empty string nonsense
- ASSERT_EQ(a.substr(99, 2), e);
- ASSERT_EQ(d.substr(99), e);
- ASSERT_EQ(d.substr(0, 99), e);
- ASSERT_EQ(d.substr(99, 99), e);
-}
-
-TYPED_TEST(CommonStringPieceTest, CheckCustom) {
- TypeParam foobar(TestFixture::as_string("foobar"));
- BasicStringPiece<TypeParam> a(foobar);
- TypeParam s1(TestFixture::as_string("123"));
- s1 += static_cast<typename TypeParam::value_type>('\0');
- s1 += TestFixture::as_string("456");
- BasicStringPiece<TypeParam> b(s1);
- BasicStringPiece<TypeParam> e;
- TypeParam s2;
-
- // remove_prefix
- BasicStringPiece<TypeParam> c(a);
- c.remove_prefix(3);
- ASSERT_EQ(c, TestFixture::as_string("bar"));
- c = a;
- c.remove_prefix(0);
- ASSERT_EQ(c, a);
- c.remove_prefix(c.size());
- ASSERT_EQ(c, e);
-
- // remove_suffix
- c = a;
- c.remove_suffix(3);
- ASSERT_EQ(c, TestFixture::as_string("foo"));
- c = a;
- c.remove_suffix(0);
- ASSERT_EQ(c, a);
- c.remove_suffix(c.size());
- ASSERT_EQ(c, e);
-
- // set
- c.set(foobar.c_str());
- ASSERT_EQ(c, a);
- c.set(foobar.c_str(), 6);
- ASSERT_EQ(c, a);
- c.set(foobar.c_str(), 0);
- ASSERT_EQ(c, e);
- c.set(foobar.c_str(), 7); // Note, has an embedded NULL
- ASSERT_NE(c, a);
-
- // as_string
- TypeParam s3(a.as_string().c_str(), 7); // Note, has an embedded NULL
- ASSERT_EQ(c, s3);
- TypeParam s4(e.as_string());
- ASSERT_TRUE(s4.empty());
-
- // operator STRING_TYPE()
- TypeParam s5(TypeParam(a).c_str(), 7); // Note, has an embedded NULL
- ASSERT_EQ(c, s5);
- TypeParam s6(e);
- ASSERT_TRUE(s6.empty());
-}
-
-TEST(StringPieceTest, CheckCustom) {
- StringPiece a("foobar");
- std::string s1("123");
- s1 += '\0';
- s1 += "456";
- StringPiece b(s1);
- StringPiece e;
- std::string s2;
-
- // CopyToString
- a.CopyToString(&s2);
- ASSERT_EQ(s2.size(), 6U);
- ASSERT_EQ(s2, "foobar");
- b.CopyToString(&s2);
- ASSERT_EQ(s2.size(), 7U);
- ASSERT_EQ(s1, s2);
- e.CopyToString(&s2);
- ASSERT_TRUE(s2.empty());
-
- // AppendToString
- s2.erase();
- a.AppendToString(&s2);
- ASSERT_EQ(s2.size(), 6U);
- ASSERT_EQ(s2, "foobar");
- a.AppendToString(&s2);
- ASSERT_EQ(s2.size(), 12U);
- ASSERT_EQ(s2, "foobarfoobar");
-
- // starts_with
- ASSERT_TRUE(a.starts_with(a));
- ASSERT_TRUE(a.starts_with("foo"));
- ASSERT_TRUE(a.starts_with(e));
- ASSERT_TRUE(b.starts_with(s1));
- ASSERT_TRUE(b.starts_with(b));
- ASSERT_TRUE(b.starts_with(e));
- ASSERT_TRUE(e.starts_with(""));
- ASSERT_TRUE(!a.starts_with(b));
- ASSERT_TRUE(!b.starts_with(a));
- ASSERT_TRUE(!e.starts_with(a));
-
- // ends with
- ASSERT_TRUE(a.ends_with(a));
- ASSERT_TRUE(a.ends_with("bar"));
- ASSERT_TRUE(a.ends_with(e));
- ASSERT_TRUE(b.ends_with(s1));
- ASSERT_TRUE(b.ends_with(b));
- ASSERT_TRUE(b.ends_with(e));
- ASSERT_TRUE(e.ends_with(""));
- ASSERT_TRUE(!a.ends_with(b));
- ASSERT_TRUE(!b.ends_with(a));
- ASSERT_TRUE(!e.ends_with(a));
-
- StringPiece c;
- c.set("foobar", 6);
- ASSERT_EQ(c, a);
- c.set("foobar", 0);
- ASSERT_EQ(c, e);
- c.set("foobar", 7);
- ASSERT_NE(c, a);
-}
-
-TYPED_TEST(CommonStringPieceTest, CheckNULL) {
- // we used to crash here, but now we don't.
- BasicStringPiece<TypeParam> s(nullptr);
- ASSERT_EQ(s.data(), nullptr);
- ASSERT_EQ(s.size(), 0U);
-
- s.set(nullptr);
- ASSERT_EQ(s.data(), nullptr);
- ASSERT_EQ(s.size(), 0U);
-
- TypeParam str(s);
- ASSERT_EQ(str.length(), 0U);
- ASSERT_EQ(str, TypeParam());
-
- str = s.as_string();
- ASSERT_EQ(str.length(), 0U);
- ASSERT_EQ(str, TypeParam());
-}
-
-TYPED_TEST(CommonStringPieceTest, CheckComparisons2) {
- TypeParam alphabet(TestFixture::as_string("abcdefghijklmnopqrstuvwxyz"));
- TypeParam alphabet_z(TestFixture::as_string("abcdefghijklmnopqrstuvwxyzz"));
- TypeParam alphabet_y(TestFixture::as_string("abcdefghijklmnopqrstuvwxyy"));
- BasicStringPiece<TypeParam> abc(alphabet);
-
- // check comparison operations on strings longer than 4 bytes.
- ASSERT_EQ(abc, BasicStringPiece<TypeParam>(alphabet));
- ASSERT_EQ(abc.compare(BasicStringPiece<TypeParam>(alphabet)), 0);
-
- ASSERT_TRUE(abc < BasicStringPiece<TypeParam>(alphabet_z));
- ASSERT_LT(abc.compare(BasicStringPiece<TypeParam>(alphabet_z)), 0);
-
- ASSERT_TRUE(abc > BasicStringPiece<TypeParam>(alphabet_y));
- ASSERT_GT(abc.compare(BasicStringPiece<TypeParam>(alphabet_y)), 0);
-}
-
-// Test operations only supported by std::string version.
-TEST(StringPieceTest, CheckComparisons2) {
- StringPiece abc("abcdefghijklmnopqrstuvwxyz");
-
- // starts_with
- ASSERT_TRUE(abc.starts_with(abc));
- ASSERT_TRUE(abc.starts_with("abcdefghijklm"));
- ASSERT_TRUE(!abc.starts_with("abcdefguvwxyz"));
-
- // ends_with
- ASSERT_TRUE(abc.ends_with(abc));
- ASSERT_TRUE(!abc.ends_with("abcdefguvwxyz"));
- ASSERT_TRUE(abc.ends_with("nopqrstuvwxyz"));
-}
-
-TYPED_TEST(CommonStringPieceTest, StringCompareNotAmbiguous) {
- ASSERT_TRUE(TestFixture::as_string("hello").c_str() ==
- TestFixture::as_string("hello"));
- ASSERT_TRUE(TestFixture::as_string("hello").c_str() <
- TestFixture::as_string("world"));
-}
-
-TYPED_TEST(CommonStringPieceTest, HeterogenousStringPieceEquals) {
- TypeParam hello(TestFixture::as_string("hello"));
-
- ASSERT_EQ(BasicStringPiece<TypeParam>(hello), hello);
- ASSERT_EQ(hello.c_str(), BasicStringPiece<TypeParam>(hello));
-}
-
-// string16-specific stuff
-TEST(StringPiece16Test, CheckSTL) {
- // Check some non-ascii characters.
- string16 fifth(ASCIIToUTF16("123"));
- fifth.push_back(0x0000);
- fifth.push_back(0xd8c5);
- fifth.push_back(0xdffe);
- StringPiece16 f(fifth);
-
- ASSERT_EQ(f[3], '\0');
- ASSERT_EQ(f[5], static_cast<char16>(0xdffe));
-
- ASSERT_EQ(f.size(), 6U);
-}
-
-
-
-TEST(StringPiece16Test, CheckConversion) {
- // Make sure that we can convert from UTF8 to UTF16 and back. We use a two
- // byte character (G clef) to test this.
- ASSERT_EQ(
- UTF16ToUTF8(
- StringPiece16(UTF8ToUTF16("\xf0\x9d\x84\x9e")).as_string()),
- "\xf0\x9d\x84\x9e");
-}
-
-TYPED_TEST(CommonStringPieceTest, CheckConstructors) {
- TypeParam str(TestFixture::as_string("hello world"));
- TypeParam empty;
-
- ASSERT_EQ(str, BasicStringPiece<TypeParam>(str));
- ASSERT_EQ(str, BasicStringPiece<TypeParam>(str.c_str()));
- ASSERT_TRUE(TestFixture::as_string("hello") ==
- BasicStringPiece<TypeParam>(str.c_str(), 5));
- ASSERT_EQ(
- empty,
- BasicStringPiece<TypeParam>(
- str.c_str(),
- static_cast<typename BasicStringPiece<TypeParam>::size_type>(0)));
- ASSERT_EQ(empty, BasicStringPiece<TypeParam>(nullptr));
- ASSERT_TRUE(
- empty ==
- BasicStringPiece<TypeParam>(
- nullptr,
- static_cast<typename BasicStringPiece<TypeParam>::size_type>(0)));
- ASSERT_EQ(empty, BasicStringPiece<TypeParam>());
- ASSERT_EQ(str, BasicStringPiece<TypeParam>(str.begin(), str.end()));
- ASSERT_EQ(empty, BasicStringPiece<TypeParam>(str.begin(), str.begin()));
- ASSERT_EQ(empty, BasicStringPiece<TypeParam>(empty));
- ASSERT_EQ(empty, BasicStringPiece<TypeParam>(empty.begin(), empty.end()));
-}
-
-TEST(StringPieceTest, ConstexprCtor) {
- {
- constexpr StringPiece piece;
- std::ignore = piece;
- }
-
- {
- constexpr StringPiece piece("abc");
- std::ignore = piece;
- }
-
- {
- constexpr StringPiece piece("abc", 2);
- std::ignore = piece;
- }
-}
-
-TEST(StringPieceTest, ConstexprData) {
- {
- constexpr StringPiece piece;
- static_assert(piece.data() == nullptr, "");
- }
-
- {
- constexpr StringPiece piece("abc");
- static_assert(piece.data()[0] == 'a', "");
- static_assert(piece.data()[1] == 'b', "");
- static_assert(piece.data()[2] == 'c', "");
- }
-
- {
- constexpr StringPiece piece("def", 2);
- static_assert(piece.data()[0] == 'd', "");
- static_assert(piece.data()[1] == 'e', "");
- }
-}
-
-TEST(StringPieceTest, ConstexprSize) {
- {
- constexpr StringPiece piece;
- static_assert(piece.size() == 0, "");
- }
-
- {
- constexpr StringPiece piece("abc");
- static_assert(piece.size() == 3, "");
- }
-
- {
- constexpr StringPiece piece("def", 2);
- static_assert(piece.size() == 2, "");
- }
-}
-
-TEST(StringPieceTest, Compare) {
- constexpr StringPiece piece = "def";
-
- static_assert(piece.compare("ab") == 1, "");
- static_assert(piece.compare("abc") == 1, "");
- static_assert(piece.compare("abcd") == 1, "");
- static_assert(piece.compare("de") == 1, "");
- static_assert(piece.compare("def") == 0, "");
- static_assert(piece.compare("defg") == -1, "");
- static_assert(piece.compare("gh") == -1, "");
- static_assert(piece.compare("ghi") == -1, "");
- static_assert(piece.compare("ghij") == -1, "");
-}
-
-TEST(StringPieceTest, StartsWith) {
- constexpr StringPiece piece("abc");
-
- static_assert(piece.starts_with(""), "");
- static_assert(piece.starts_with("a"), "");
- static_assert(piece.starts_with("ab"), "");
- static_assert(piece.starts_with("abc"), "");
-
- static_assert(!piece.starts_with("b"), "");
- static_assert(!piece.starts_with("bc"), "");
-
- static_assert(!piece.starts_with("abcd"), "");
-}
-
-TEST(StringPieceTest, EndsWith) {
- constexpr StringPiece piece("abc");
-
- static_assert(piece.ends_with(""), "");
- static_assert(piece.ends_with("c"), "");
- static_assert(piece.ends_with("bc"), "");
- static_assert(piece.ends_with("abc"), "");
-
- static_assert(!piece.ends_with("a"), "");
- static_assert(!piece.ends_with("ab"), "");
-
- static_assert(!piece.ends_with("abcd"), "");
-}
-
-} // namespace base
diff --git a/base/strings/string_split_unittest.cc b/base/strings/string_split_unittest.cc
deleted file mode 100644
index bf09aa5..0000000
--- a/base/strings/string_split_unittest.cc
+++ /dev/null
@@ -1,386 +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/strings/string_split.h"
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-
-namespace base {
-
-class SplitStringIntoKeyValuePairsTest : public testing::Test {
- protected:
- base::StringPairs kv_pairs;
-};
-
-TEST_F(SplitStringIntoKeyValuePairsTest, EmptyString) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs(std::string(),
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- EXPECT_TRUE(kv_pairs.empty());
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, MissingKeyValueDelimiter) {
- EXPECT_FALSE(SplitStringIntoKeyValuePairs("key1,key2:value2",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_TRUE(kv_pairs[0].first.empty());
- EXPECT_TRUE(kv_pairs[0].second.empty());
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, EmptyKeyWithKeyValueDelimiter) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs(":value1,key2:value2",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_TRUE(kv_pairs[0].first.empty());
- EXPECT_EQ("value1", kv_pairs[0].second);
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, TrailingAndLeadingPairDelimiter) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs(",key1:value1,key2:value2,",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ("key1", kv_pairs[0].first);
- EXPECT_EQ("value1", kv_pairs[0].second);
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, EmptyPair) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:value1,,key3:value3",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ("key1", kv_pairs[0].first);
- EXPECT_EQ("value1", kv_pairs[0].second);
- EXPECT_EQ("key3", kv_pairs[1].first);
- EXPECT_EQ("value3", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, EmptyValue) {
- EXPECT_FALSE(SplitStringIntoKeyValuePairs("key1:,key2:value2",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ("key1", kv_pairs[0].first);
- EXPECT_EQ("", kv_pairs[0].second);
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, UntrimmedWhitespace) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1 : value1",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(1U, kv_pairs.size());
- EXPECT_EQ("key1 ", kv_pairs[0].first);
- EXPECT_EQ(" value1", kv_pairs[0].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, TrimmedWhitespace) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:value1 , key2:value2",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ("key1", kv_pairs[0].first);
- EXPECT_EQ("value1", kv_pairs[0].second);
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, MultipleKeyValueDelimiters) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:::value1,key2:value2",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ("key1", kv_pairs[0].first);
- EXPECT_EQ("value1", kv_pairs[0].second);
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST_F(SplitStringIntoKeyValuePairsTest, OnlySplitAtGivenSeparator) {
- std::string a("a ?!@#$%^&*()_+:/{}\\\t\nb");
- EXPECT_TRUE(SplitStringIntoKeyValuePairs(a + "X" + a + "Y" + a + "X" + a,
- 'X', // Key-value delimiter
- 'Y', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ(a, kv_pairs[0].first);
- EXPECT_EQ(a, kv_pairs[0].second);
- EXPECT_EQ(a, kv_pairs[1].first);
- EXPECT_EQ(a, kv_pairs[1].second);
-}
-
-
-TEST_F(SplitStringIntoKeyValuePairsTest, DelimiterInValue) {
- EXPECT_TRUE(SplitStringIntoKeyValuePairs("key1:va:ue1,key2:value2",
- ':', // Key-value delimiter
- ',', // Key-value pair delimiter
- &kv_pairs));
- ASSERT_EQ(2U, kv_pairs.size());
- EXPECT_EQ("key1", kv_pairs[0].first);
- EXPECT_EQ("va:ue1", kv_pairs[0].second);
- EXPECT_EQ("key2", kv_pairs[1].first);
- EXPECT_EQ("value2", kv_pairs[1].second);
-}
-
-TEST(SplitStringUsingSubstrTest, EmptyString) {
- std::vector<std::string> results = SplitStringUsingSubstr(
- std::string(), "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(1u, results.size());
- EXPECT_THAT(results, ElementsAre(""));
-}
-
-TEST(StringUtilTest, SplitString_Basics) {
- std::vector<std::string> r;
-
- r = SplitString(std::string(), ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- EXPECT_TRUE(r.empty());
-
- // Empty separator list
- r = SplitString("hello, world", "", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(1u, r.size());
- EXPECT_EQ("hello, world", r[0]);
-
- // Should split on any of the separators.
- r = SplitString("::,,;;", ",:;", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(7u, r.size());
- for (auto str : r)
- ASSERT_TRUE(str.empty());
-
- r = SplitString("red, green; blue:", ",:;", TRIM_WHITESPACE,
- SPLIT_WANT_NONEMPTY);
- ASSERT_EQ(3u, r.size());
- EXPECT_EQ("red", r[0]);
- EXPECT_EQ("green", r[1]);
- EXPECT_EQ("blue", r[2]);
-
- // Want to split a string along whitespace sequences.
- r = SplitString(" red green \tblue\n", " \t\n", TRIM_WHITESPACE,
- SPLIT_WANT_NONEMPTY);
- ASSERT_EQ(3u, r.size());
- EXPECT_EQ("red", r[0]);
- EXPECT_EQ("green", r[1]);
- EXPECT_EQ("blue", r[2]);
-
- // Weird case of splitting on spaces but not trimming.
- r = SplitString(" red ", " ", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(3u, r.size());
- EXPECT_EQ("", r[0]); // Before the first space.
- EXPECT_EQ("red", r[1]);
- EXPECT_EQ("", r[2]); // After the last space.
-}
-
-TEST(StringUtilTest, SplitString_WhitespaceAndResultType) {
- std::vector<std::string> r;
-
- // Empty input handling.
- r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- EXPECT_TRUE(r.empty());
- r = SplitString(std::string(), ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
- EXPECT_TRUE(r.empty());
-
- // Input string is space and we're trimming.
- r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(1u, r.size());
- EXPECT_EQ("", r[0]);
- r = SplitString(" ", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
- EXPECT_TRUE(r.empty());
-
- // Test all 4 combinations of flags on ", ,".
- r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(3u, r.size());
- EXPECT_EQ("", r[0]);
- EXPECT_EQ(" ", r[1]);
- EXPECT_EQ("", r[2]);
- r = SplitString(", ,", ",", KEEP_WHITESPACE, SPLIT_WANT_NONEMPTY);
- ASSERT_EQ(1u, r.size());
- ASSERT_EQ(" ", r[0]);
- r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(3u, r.size());
- EXPECT_EQ("", r[0]);
- EXPECT_EQ("", r[1]);
- EXPECT_EQ("", r[2]);
- r = SplitString(", ,", ",", TRIM_WHITESPACE, SPLIT_WANT_NONEMPTY);
- ASSERT_TRUE(r.empty());
-}
-
-TEST(SplitStringUsingSubstrTest, StringWithNoDelimiter) {
- std::vector<std::string> results = SplitStringUsingSubstr(
- "alongwordwithnodelimiter", "DELIMITER", TRIM_WHITESPACE,
- SPLIT_WANT_ALL);
- ASSERT_EQ(1u, results.size());
- EXPECT_THAT(results, ElementsAre("alongwordwithnodelimiter"));
-}
-
-TEST(SplitStringUsingSubstrTest, LeadingDelimitersSkipped) {
- std::vector<std::string> results = SplitStringUsingSubstr(
- "DELIMITERDELIMITERDELIMITERoneDELIMITERtwoDELIMITERthree",
- "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(6u, results.size());
- EXPECT_THAT(results, ElementsAre("", "", "", "one", "two", "three"));
-}
-
-TEST(SplitStringUsingSubstrTest, ConsecutiveDelimitersSkipped) {
- std::vector<std::string> results = SplitStringUsingSubstr(
- "unoDELIMITERDELIMITERDELIMITERdosDELIMITERtresDELIMITERDELIMITERcuatro",
- "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(7u, results.size());
- EXPECT_THAT(results, ElementsAre("uno", "", "", "dos", "tres", "", "cuatro"));
-}
-
-TEST(SplitStringUsingSubstrTest, TrailingDelimitersSkipped) {
- std::vector<std::string> results = SplitStringUsingSubstr(
- "unDELIMITERdeuxDELIMITERtroisDELIMITERquatreDELIMITERDELIMITERDELIMITER",
- "DELIMITER", TRIM_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(7u, results.size());
- EXPECT_THAT(
- results, ElementsAre("un", "deux", "trois", "quatre", "", "", ""));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, StringWithNoDelimiter) {
- std::vector<base::StringPiece> results =
- SplitStringPieceUsingSubstr("alongwordwithnodelimiter", "DELIMITER",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(1u, results.size());
- EXPECT_THAT(results, ElementsAre("alongwordwithnodelimiter"));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, LeadingDelimitersSkipped) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "DELIMITERDELIMITERDELIMITERoneDELIMITERtwoDELIMITERthree", "DELIMITER",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(6u, results.size());
- EXPECT_THAT(results, ElementsAre("", "", "", "one", "two", "three"));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, ConsecutiveDelimitersSkipped) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "unoDELIMITERDELIMITERDELIMITERdosDELIMITERtresDELIMITERDELIMITERcuatro",
- "DELIMITER", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(7u, results.size());
- EXPECT_THAT(results, ElementsAre("uno", "", "", "dos", "tres", "", "cuatro"));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, TrailingDelimitersSkipped) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "unDELIMITERdeuxDELIMITERtroisDELIMITERquatreDELIMITERDELIMITERDELIMITER",
- "DELIMITER", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(7u, results.size());
- EXPECT_THAT(results,
- ElementsAre("un", "deux", "trois", "quatre", "", "", ""));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, KeepWhitespace) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "un DELIMITERdeux\tDELIMITERtrois\nDELIMITERquatre", "DELIMITER",
- base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(4u, results.size());
- EXPECT_THAT(results, ElementsAre("un ", "deux\t", "trois\n", "quatre"));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, TrimWhitespace) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "un DELIMITERdeux\tDELIMITERtrois\nDELIMITERquatre", "DELIMITER",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(4u, results.size());
- EXPECT_THAT(results, ElementsAre("un", "deux", "trois", "quatre"));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, SplitWantAll) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "unDELIMITERdeuxDELIMITERtroisDELIMITERDELIMITER", "DELIMITER",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(5u, results.size());
- EXPECT_THAT(results, ElementsAre("un", "deux", "trois", "", ""));
-}
-
-TEST(SplitStringPieceUsingSubstrTest, SplitWantNonEmpty) {
- std::vector<base::StringPiece> results = SplitStringPieceUsingSubstr(
- "unDELIMITERdeuxDELIMITERtroisDELIMITERDELIMITER", "DELIMITER",
- base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- ASSERT_EQ(3u, results.size());
- EXPECT_THAT(results, ElementsAre("un", "deux", "trois"));
-}
-
-TEST(StringSplitTest, StringSplitKeepWhitespace) {
- std::vector<std::string> r;
-
- r = SplitString(" ", "*", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL);
- ASSERT_EQ(1U, r.size());
- EXPECT_EQ(r[0], " ");
-
- r = SplitString("\t \ta\t ", "\t", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_ALL);
- ASSERT_EQ(4U, r.size());
- EXPECT_EQ(r[0], "");
- EXPECT_EQ(r[1], " ");
- EXPECT_EQ(r[2], "a");
- EXPECT_EQ(r[3], " ");
-
- r = SplitString("\ta\t\nb\tcc", "\n", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_ALL);
- ASSERT_EQ(2U, r.size());
- EXPECT_EQ(r[0], "\ta\t");
- EXPECT_EQ(r[1], "b\tcc");
-}
-
-TEST(StringSplitTest, SplitStringAlongWhitespace) {
- struct TestData {
- const char* input;
- const size_t expected_result_count;
- const char* output1;
- const char* output2;
- } data[] = {
- { "a", 1, "a", "" },
- { " ", 0, "", "" },
- { " a", 1, "a", "" },
- { " ab ", 1, "ab", "" },
- { " ab c", 2, "ab", "c" },
- { " ab c ", 2, "ab", "c" },
- { " ab cd", 2, "ab", "cd" },
- { " ab cd ", 2, "ab", "cd" },
- { " \ta\t", 1, "a", "" },
- { " b\ta\t", 2, "b", "a" },
- { " b\tat", 2, "b", "at" },
- { "b\tat", 2, "b", "at" },
- { "b\t at", 2, "b", "at" },
- };
- for (size_t i = 0; i < arraysize(data); ++i) {
- std::vector<std::string> results = base::SplitString(
- data[i].input, kWhitespaceASCII, base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
- ASSERT_EQ(data[i].expected_result_count, results.size());
- if (data[i].expected_result_count > 0)
- ASSERT_EQ(data[i].output1, results[0]);
- if (data[i].expected_result_count > 1)
- ASSERT_EQ(data[i].output2, results[1]);
- }
-}
-
-} // namespace base
diff --git a/base/strings/string_tokenizer_unittest.cc b/base/strings/string_tokenizer_unittest.cc
deleted file mode 100644
index d391845..0000000
--- a/base/strings/string_tokenizer_unittest.cc
+++ /dev/null
@@ -1,234 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. 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/string_tokenizer.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-using std::string;
-
-namespace base {
-
-namespace {
-
-TEST(StringTokenizerTest, Simple) {
- string input = "this is a test";
- StringTokenizer t(input, " ");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("this"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("is"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("a"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("test"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, Reset) {
- string input = "this is a test";
- StringTokenizer t(input, " ");
-
- for (int i = 0; i < 2; ++i) {
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("this"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("is"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("a"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("test"), t.token());
-
- EXPECT_FALSE(t.GetNext());
- t.Reset();
- }
-}
-
-TEST(StringTokenizerTest, RetDelims) {
- string input = "this is a test";
- StringTokenizer t(input, " ");
- t.set_options(StringTokenizer::RETURN_DELIMS);
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("this"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string(" "), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("is"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string(" "), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("a"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string(" "), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("test"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, ManyDelims) {
- string input = "this: is, a-test";
- StringTokenizer t(input, ": ,-");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("this"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("is"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("a"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("test"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, ParseHeader) {
- string input = "Content-Type: text/html ; charset=UTF-8";
- StringTokenizer t(input, ": ;=");
- t.set_options(StringTokenizer::RETURN_DELIMS);
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_FALSE(t.token_is_delim());
- EXPECT_EQ(string("Content-Type"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_TRUE(t.token_is_delim());
- EXPECT_EQ(string(":"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_TRUE(t.token_is_delim());
- EXPECT_EQ(string(" "), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_FALSE(t.token_is_delim());
- EXPECT_EQ(string("text/html"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_TRUE(t.token_is_delim());
- EXPECT_EQ(string(" "), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_TRUE(t.token_is_delim());
- EXPECT_EQ(string(";"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_TRUE(t.token_is_delim());
- EXPECT_EQ(string(" "), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_FALSE(t.token_is_delim());
- EXPECT_EQ(string("charset"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_TRUE(t.token_is_delim());
- EXPECT_EQ(string("="), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_FALSE(t.token_is_delim());
- EXPECT_EQ(string("UTF-8"), t.token());
-
- EXPECT_FALSE(t.GetNext());
- EXPECT_FALSE(t.token_is_delim());
-}
-
-TEST(StringTokenizerTest, ParseQuotedString) {
- string input = "foo bar 'hello world' baz";
- StringTokenizer t(input, " ");
- t.set_quote_chars("'");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("foo"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("bar"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("'hello world'"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("baz"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, ParseQuotedString_Malformed) {
- string input = "bar 'hello wo";
- StringTokenizer t(input, " ");
- t.set_quote_chars("'");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("bar"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("'hello wo"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, ParseQuotedString_Multiple) {
- string input = "bar 'hel\"lo\" wo' baz\"";
- StringTokenizer t(input, " ");
- t.set_quote_chars("'\"");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("bar"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("'hel\"lo\" wo'"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("baz\""), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, ParseQuotedString_EscapedQuotes) {
- string input = "foo 'don\\'t do that'";
- StringTokenizer t(input, " ");
- t.set_quote_chars("'");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("foo"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("'don\\'t do that'"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-TEST(StringTokenizerTest, ParseQuotedString_EscapedQuotes2) {
- string input = "foo='a, b', bar";
- StringTokenizer t(input, ", ");
- t.set_quote_chars("'");
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("foo='a, b'"), t.token());
-
- EXPECT_TRUE(t.GetNext());
- EXPECT_EQ(string("bar"), t.token());
-
- EXPECT_FALSE(t.GetNext());
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/strings/string_util_unittest.cc b/base/strings/string_util_unittest.cc
deleted file mode 100644
index 509889e..0000000
--- a/base/strings/string_util_unittest.cc
+++ /dev/null
@@ -1,1379 +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/string_util.h"
-
-#include <math.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "base/strings/string16.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::ElementsAre;
-
-namespace base {
-
-static const struct trim_case {
- const wchar_t* input;
- const TrimPositions positions;
- const wchar_t* output;
- const TrimPositions return_value;
-} trim_cases[] = {
- {L" Google Video ", TRIM_LEADING, L"Google Video ", TRIM_LEADING},
- {L" Google Video ", TRIM_TRAILING, L" Google Video", TRIM_TRAILING},
- {L" Google Video ", TRIM_ALL, L"Google Video", TRIM_ALL},
- {L"Google Video", TRIM_ALL, L"Google Video", TRIM_NONE},
- {L"", TRIM_ALL, L"", TRIM_NONE},
- {L" ", TRIM_LEADING, L"", TRIM_LEADING},
- {L" ", TRIM_TRAILING, L"", TRIM_TRAILING},
- {L" ", TRIM_ALL, L"", TRIM_ALL},
- {L"\t\rTest String\n", TRIM_ALL, L"Test String", TRIM_ALL},
- {L"\x2002Test String\x00A0\x3000", TRIM_ALL, L"Test String", TRIM_ALL},
-};
-
-static const struct trim_case_ascii {
- const char* input;
- const TrimPositions positions;
- const char* output;
- const TrimPositions return_value;
-} trim_cases_ascii[] = {
- {" Google Video ", TRIM_LEADING, "Google Video ", TRIM_LEADING},
- {" Google Video ", TRIM_TRAILING, " Google Video", TRIM_TRAILING},
- {" Google Video ", TRIM_ALL, "Google Video", TRIM_ALL},
- {"Google Video", TRIM_ALL, "Google Video", TRIM_NONE},
- {"", TRIM_ALL, "", TRIM_NONE},
- {" ", TRIM_LEADING, "", TRIM_LEADING},
- {" ", TRIM_TRAILING, "", TRIM_TRAILING},
- {" ", TRIM_ALL, "", TRIM_ALL},
- {"\t\rTest String\n", TRIM_ALL, "Test String", TRIM_ALL},
-};
-
-namespace {
-
-// Helper used to test TruncateUTF8ToByteSize.
-bool Truncated(const std::string& input,
- const size_t byte_size,
- std::string* output) {
- size_t prev = input.length();
- TruncateUTF8ToByteSize(input, byte_size, output);
- return prev != output->length();
-}
-
-} // namespace
-
-TEST(StringUtilTest, TruncateUTF8ToByteSize) {
- std::string output;
-
- // Empty strings and invalid byte_size arguments
- EXPECT_FALSE(Truncated(std::string(), 0, &output));
- EXPECT_EQ(output, "");
- EXPECT_TRUE(Truncated("\xe1\x80\xbf", 0, &output));
- EXPECT_EQ(output, "");
- EXPECT_FALSE(Truncated("\xe1\x80\xbf", static_cast<size_t>(-1), &output));
- EXPECT_FALSE(Truncated("\xe1\x80\xbf", 4, &output));
-
- // Testing the truncation of valid UTF8 correctly
- EXPECT_TRUE(Truncated("abc", 2, &output));
- EXPECT_EQ(output, "ab");
- EXPECT_TRUE(Truncated("\xc2\x81\xc2\x81", 2, &output));
- EXPECT_EQ(output.compare("\xc2\x81"), 0);
- EXPECT_TRUE(Truncated("\xc2\x81\xc2\x81", 3, &output));
- EXPECT_EQ(output.compare("\xc2\x81"), 0);
- EXPECT_FALSE(Truncated("\xc2\x81\xc2\x81", 4, &output));
- EXPECT_EQ(output.compare("\xc2\x81\xc2\x81"), 0);
-
- {
- const char array[] = "\x00\x00\xc2\x81\xc2\x81";
- const std::string array_string(array, arraysize(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\x00\x00\xc2\x81", 4)), 0);
- }
-
- {
- const char array[] = "\x00\xc2\x81\xc2\x81";
- const std::string array_string(array, arraysize(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\x00\xc2\x81", 3)), 0);
- }
-
- // Testing invalid UTF8
- EXPECT_TRUE(Truncated("\xed\xa0\x80\xed\xbf\xbf", 6, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xed\xa0\x8f", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xed\xbf\xbf", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
-
- // Testing invalid UTF8 mixed with valid UTF8
- EXPECT_FALSE(Truncated("\xe1\x80\xbf", 3, &output));
- EXPECT_EQ(output.compare("\xe1\x80\xbf"), 0);
- EXPECT_FALSE(Truncated("\xf1\x80\xa0\xbf", 4, &output));
- EXPECT_EQ(output.compare("\xf1\x80\xa0\xbf"), 0);
- EXPECT_FALSE(Truncated("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf",
- 10, &output));
- EXPECT_EQ(output.compare("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"), 0);
- EXPECT_TRUE(Truncated("a\xc2\x81\xe1\x80\xbf\xf1""a""\x80\xa0",
- 10, &output));
- EXPECT_EQ(output.compare("a\xc2\x81\xe1\x80\xbf\xf1""a"), 0);
- EXPECT_FALSE(Truncated("\xef\xbb\xbf" "abc", 6, &output));
- EXPECT_EQ(output.compare("\xef\xbb\xbf" "abc"), 0);
-
- // Overlong sequences
- EXPECT_TRUE(Truncated("\xc0\x80", 2, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xc1\x80\xc1\x81", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xe0\x80\x80", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xe0\x82\x80", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xe0\x9f\xbf", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x80\x80\x8D", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x80\x82\x91", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x80\xa0\x80", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x8f\xbb\xbf", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf8\x80\x80\x80\xbf", 5, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xfc\x80\x80\x80\xa0\xa5", 6, &output));
- EXPECT_EQ(output.compare(""), 0);
-
- // Beyond U+10FFFF (the upper limit of Unicode codespace)
- EXPECT_TRUE(Truncated("\xf4\x90\x80\x80", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf8\xa0\xbf\x80\xbf", 5, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xfc\x9c\xbf\x80\xbf\x80", 6, &output));
- EXPECT_EQ(output.compare(""), 0);
-
- // BOMs in UTF-16(BE|LE) and UTF-32(BE|LE)
- EXPECT_TRUE(Truncated("\xfe\xff", 2, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xff\xfe", 2, &output));
- EXPECT_EQ(output.compare(""), 0);
-
- {
- const char array[] = "\x00\x00\xfe\xff";
- const std::string array_string(array, arraysize(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\x00\x00", 2)), 0);
- }
-
- // Variants on the previous test
- {
- const char array[] = "\xff\xfe\x00\x00";
- const std::string array_string(array, 4);
- EXPECT_FALSE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\xff\xfe\x00\x00", 4)), 0);
- }
- {
- const char array[] = "\xff\x00\x00\xfe";
- const std::string array_string(array, arraysize(array));
- EXPECT_TRUE(Truncated(array_string, 4, &output));
- EXPECT_EQ(output.compare(std::string("\xff\x00\x00", 3)), 0);
- }
-
- // Non-characters : U+xxFFF[EF] where xx is 0x00 through 0x10 and <FDD0,FDEF>
- EXPECT_TRUE(Truncated("\xef\xbf\xbe", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf0\x8f\xbf\xbe", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xf3\xbf\xbf\xbf", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xef\xb7\x90", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_TRUE(Truncated("\xef\xb7\xaf", 3, &output));
- EXPECT_EQ(output.compare(""), 0);
-
- // Strings in legacy encodings that are valid in UTF-8, but
- // are invalid as UTF-8 in real data.
- EXPECT_TRUE(Truncated("caf\xe9", 4, &output));
- EXPECT_EQ(output.compare("caf"), 0);
- EXPECT_TRUE(Truncated("\xb0\xa1\xb0\xa2", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
- EXPECT_FALSE(Truncated("\xa7\x41\xa6\x6e", 4, &output));
- EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
- EXPECT_TRUE(Truncated("\xa7\x41\xa6\x6e\xd9\xee\xe4\xee", 7,
- &output));
- EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
-
- // Testing using the same string as input and output.
- EXPECT_FALSE(Truncated(output, 4, &output));
- EXPECT_EQ(output.compare("\xa7\x41\xa6\x6e"), 0);
- EXPECT_TRUE(Truncated(output, 3, &output));
- EXPECT_EQ(output.compare("\xa7\x41"), 0);
-
- // "abc" with U+201[CD] in windows-125[0-8]
- EXPECT_TRUE(Truncated("\x93" "abc\x94", 5, &output));
- EXPECT_EQ(output.compare("\x93" "abc"), 0);
-
- // U+0639 U+064E U+0644 U+064E in ISO-8859-6
- EXPECT_TRUE(Truncated("\xd9\xee\xe4\xee", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
-
- // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
- EXPECT_TRUE(Truncated("\xe3\xe5\xe9\xdC", 4, &output));
- EXPECT_EQ(output.compare(""), 0);
-}
-
-TEST(StringUtilTest, TrimWhitespace) {
- string16 output; // Allow contents to carry over to next testcase
- for (size_t i = 0; i < arraysize(trim_cases); ++i) {
- const trim_case& value = trim_cases[i];
- EXPECT_EQ(value.return_value,
- TrimWhitespace(WideToUTF16(value.input), value.positions,
- &output));
- EXPECT_EQ(WideToUTF16(value.output), output);
- }
-
- // Test that TrimWhitespace() can take the same string for input and output
- output = ASCIIToUTF16(" This is a test \r\n");
- EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
- EXPECT_EQ(ASCIIToUTF16("This is a test"), output);
-
- // Once more, but with a string of whitespace
- output = ASCIIToUTF16(" \r\n");
- EXPECT_EQ(TRIM_ALL, TrimWhitespace(output, TRIM_ALL, &output));
- EXPECT_EQ(string16(), output);
-
- std::string output_ascii;
- for (size_t i = 0; i < arraysize(trim_cases_ascii); ++i) {
- const trim_case_ascii& value = trim_cases_ascii[i];
- EXPECT_EQ(value.return_value,
- TrimWhitespaceASCII(value.input, value.positions, &output_ascii));
- EXPECT_EQ(value.output, output_ascii);
- }
-}
-
-static const struct collapse_case {
- const wchar_t* input;
- const bool trim;
- const wchar_t* output;
-} collapse_cases[] = {
- {L" Google Video ", false, L"Google Video"},
- {L"Google Video", false, L"Google Video"},
- {L"", false, L""},
- {L" ", false, L""},
- {L"\t\rTest String\n", false, L"Test String"},
- {L"\x2002Test String\x00A0\x3000", false, L"Test String"},
- {L" Test \n \t String ", false, L"Test String"},
- {L"\x2002Test\x1680 \x2028 \tString\x00A0\x3000", false, L"Test String"},
- {L" Test String", false, L"Test String"},
- {L"Test String ", false, L"Test String"},
- {L"Test String", false, L"Test String"},
- {L"", true, L""},
- {L"\n", true, L""},
- {L" \r ", true, L""},
- {L"\nFoo", true, L"Foo"},
- {L"\r Foo ", true, L"Foo"},
- {L" Foo bar ", true, L"Foo bar"},
- {L" \tFoo bar \n", true, L"Foo bar"},
- {L" a \r b\n c \r\n d \t\re \t f \n ", true, L"abcde f"},
-};
-
-TEST(StringUtilTest, CollapseWhitespace) {
- for (size_t i = 0; i < arraysize(collapse_cases); ++i) {
- const collapse_case& value = collapse_cases[i];
- EXPECT_EQ(WideToUTF16(value.output),
- CollapseWhitespace(WideToUTF16(value.input), value.trim));
- }
-}
-
-static const struct collapse_case_ascii {
- const char* input;
- const bool trim;
- const char* output;
-} collapse_cases_ascii[] = {
- {" Google Video ", false, "Google Video"},
- {"Google Video", false, "Google Video"},
- {"", false, ""},
- {" ", false, ""},
- {"\t\rTest String\n", false, "Test String"},
- {" Test \n \t String ", false, "Test String"},
- {" Test String", false, "Test String"},
- {"Test String ", false, "Test String"},
- {"Test String", false, "Test String"},
- {"", true, ""},
- {"\n", true, ""},
- {" \r ", true, ""},
- {"\nFoo", true, "Foo"},
- {"\r Foo ", true, "Foo"},
- {" Foo bar ", true, "Foo bar"},
- {" \tFoo bar \n", true, "Foo bar"},
- {" a \r b\n c \r\n d \t\re \t f \n ", true, "abcde f"},
-};
-
-TEST(StringUtilTest, CollapseWhitespaceASCII) {
- for (size_t i = 0; i < arraysize(collapse_cases_ascii); ++i) {
- const collapse_case_ascii& value = collapse_cases_ascii[i];
- EXPECT_EQ(value.output, CollapseWhitespaceASCII(value.input, value.trim));
- }
-}
-
-TEST(StringUtilTest, IsStringUTF8) {
- EXPECT_TRUE(IsStringUTF8("abc"));
- EXPECT_TRUE(IsStringUTF8("\xc2\x81"));
- EXPECT_TRUE(IsStringUTF8("\xe1\x80\xbf"));
- EXPECT_TRUE(IsStringUTF8("\xf1\x80\xa0\xbf"));
- EXPECT_TRUE(IsStringUTF8("a\xc2\x81\xe1\x80\xbf\xf1\x80\xa0\xbf"));
- EXPECT_TRUE(IsStringUTF8("\xef\xbb\xbf" "abc")); // UTF-8 BOM
-
- // surrogate code points
- EXPECT_FALSE(IsStringUTF8("\xed\xa0\x80\xed\xbf\xbf"));
- EXPECT_FALSE(IsStringUTF8("\xed\xa0\x8f"));
- EXPECT_FALSE(IsStringUTF8("\xed\xbf\xbf"));
-
- // overlong sequences
- EXPECT_FALSE(IsStringUTF8("\xc0\x80")); // U+0000
- EXPECT_FALSE(IsStringUTF8("\xc1\x80\xc1\x81")); // "AB"
- EXPECT_FALSE(IsStringUTF8("\xe0\x80\x80")); // U+0000
- EXPECT_FALSE(IsStringUTF8("\xe0\x82\x80")); // U+0080
- EXPECT_FALSE(IsStringUTF8("\xe0\x9f\xbf")); // U+07ff
- EXPECT_FALSE(IsStringUTF8("\xf0\x80\x80\x8D")); // U+000D
- EXPECT_FALSE(IsStringUTF8("\xf0\x80\x82\x91")); // U+0091
- EXPECT_FALSE(IsStringUTF8("\xf0\x80\xa0\x80")); // U+0800
- EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbb\xbf")); // U+FEFF (BOM)
- EXPECT_FALSE(IsStringUTF8("\xf8\x80\x80\x80\xbf")); // U+003F
- EXPECT_FALSE(IsStringUTF8("\xfc\x80\x80\x80\xa0\xa5")); // U+00A5
-
- // Beyond U+10FFFF (the upper limit of Unicode codespace)
- EXPECT_FALSE(IsStringUTF8("\xf4\x90\x80\x80")); // U+110000
- EXPECT_FALSE(IsStringUTF8("\xf8\xa0\xbf\x80\xbf")); // 5 bytes
- EXPECT_FALSE(IsStringUTF8("\xfc\x9c\xbf\x80\xbf\x80")); // 6 bytes
-
- // BOMs in UTF-16(BE|LE) and UTF-32(BE|LE)
- EXPECT_FALSE(IsStringUTF8("\xfe\xff"));
- EXPECT_FALSE(IsStringUTF8("\xff\xfe"));
- EXPECT_FALSE(IsStringUTF8(std::string("\x00\x00\xfe\xff", 4)));
- EXPECT_FALSE(IsStringUTF8("\xff\xfe\x00\x00"));
-
- // Non-characters : U+xxFFF[EF] where xx is 0x00 through 0x10 and <FDD0,FDEF>
- EXPECT_FALSE(IsStringUTF8("\xef\xbf\xbe")); // U+FFFE)
- EXPECT_FALSE(IsStringUTF8("\xf0\x8f\xbf\xbe")); // U+1FFFE
- EXPECT_FALSE(IsStringUTF8("\xf3\xbf\xbf\xbf")); // U+10FFFF
- EXPECT_FALSE(IsStringUTF8("\xef\xb7\x90")); // U+FDD0
- EXPECT_FALSE(IsStringUTF8("\xef\xb7\xaf")); // U+FDEF
- // Strings in legacy encodings. We can certainly make up strings
- // in a legacy encoding that are valid in UTF-8, but in real data,
- // most of them are invalid as UTF-8.
- EXPECT_FALSE(IsStringUTF8("caf\xe9")); // cafe with U+00E9 in ISO-8859-1
- EXPECT_FALSE(IsStringUTF8("\xb0\xa1\xb0\xa2")); // U+AC00, U+AC001 in EUC-KR
- EXPECT_FALSE(IsStringUTF8("\xa7\x41\xa6\x6e")); // U+4F60 U+597D in Big5
- // "abc" with U+201[CD] in windows-125[0-8]
- EXPECT_FALSE(IsStringUTF8("\x93" "abc\x94"));
- // U+0639 U+064E U+0644 U+064E in ISO-8859-6
- EXPECT_FALSE(IsStringUTF8("\xd9\xee\xe4\xee"));
- // U+03B3 U+03B5 U+03B9 U+03AC in ISO-8859-7
- EXPECT_FALSE(IsStringUTF8("\xe3\xe5\xe9\xdC"));
-
- // Check that we support Embedded Nulls. The first uses the canonical UTF-8
- // representation, and the second uses a 2-byte sequence. The second version
- // is invalid UTF-8 since UTF-8 states that the shortest encoding for a
- // given codepoint must be used.
- static const char kEmbeddedNull[] = "embedded\0null";
- EXPECT_TRUE(IsStringUTF8(
- std::string(kEmbeddedNull, sizeof(kEmbeddedNull))));
- EXPECT_FALSE(IsStringUTF8("embedded\xc0\x80U+0000"));
-}
-
-TEST(StringUtilTest, IsStringASCII) {
- static char char_ascii[] =
- "0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF";
- static char16 char16_ascii[] = {
- '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', 'A',
- 'B', 'C', 'D', 'E', 'F', '0', '1', '2', '3', '4', '5', '6',
- '7', '8', '9', '0', 'A', 'B', 'C', 'D', 'E', 'F', 0 };
- static std::wstring wchar_ascii(
- L"0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF");
-
- // Test a variety of the fragment start positions and lengths in order to make
- // sure that bit masking in IsStringASCII works correctly.
- // Also, test that a non-ASCII character will be detected regardless of its
- // position inside the string.
- {
- const size_t string_length = arraysize(char_ascii) - 1;
- for (size_t offset = 0; offset < 8; ++offset) {
- for (size_t len = 0, max_len = string_length - offset; len < max_len;
- ++len) {
- EXPECT_TRUE(IsStringASCII(StringPiece(char_ascii + offset, len)));
- for (size_t char_pos = offset; char_pos < len; ++char_pos) {
- char_ascii[char_pos] |= '\x80';
- EXPECT_FALSE(IsStringASCII(StringPiece(char_ascii + offset, len)));
- char_ascii[char_pos] &= ~'\x80';
- }
- }
- }
- }
-
- {
- const size_t string_length = arraysize(char16_ascii) - 1;
- for (size_t offset = 0; offset < 4; ++offset) {
- for (size_t len = 0, max_len = string_length - offset; len < max_len;
- ++len) {
- EXPECT_TRUE(IsStringASCII(StringPiece16(char16_ascii + offset, len)));
- for (size_t char_pos = offset; char_pos < len; ++char_pos) {
- char16_ascii[char_pos] |= 0x80;
- EXPECT_FALSE(
- IsStringASCII(StringPiece16(char16_ascii + offset, len)));
- char16_ascii[char_pos] &= ~0x80;
- // Also test when the upper half is non-zero.
- char16_ascii[char_pos] |= 0x100;
- EXPECT_FALSE(
- IsStringASCII(StringPiece16(char16_ascii + offset, len)));
- char16_ascii[char_pos] &= ~0x100;
- }
- }
- }
- }
-
- {
- const size_t string_length = wchar_ascii.length();
- for (size_t len = 0; len < string_length; ++len) {
- EXPECT_TRUE(IsStringASCII(wchar_ascii.substr(0, len)));
- for (size_t char_pos = 0; char_pos < len; ++char_pos) {
- wchar_ascii[char_pos] |= 0x80;
- EXPECT_FALSE(
- IsStringASCII(wchar_ascii.substr(0, len)));
- wchar_ascii[char_pos] &= ~0x80;
- wchar_ascii[char_pos] |= 0x100;
- EXPECT_FALSE(
- IsStringASCII(wchar_ascii.substr(0, len)));
- wchar_ascii[char_pos] &= ~0x100;
-#if defined(WCHAR_T_IS_UTF32)
- wchar_ascii[char_pos] |= 0x10000;
- EXPECT_FALSE(
- IsStringASCII(wchar_ascii.substr(0, len)));
- wchar_ascii[char_pos] &= ~0x10000;
-#endif // WCHAR_T_IS_UTF32
- }
- }
- }
-}
-
-TEST(StringUtilTest, ConvertASCII) {
- static const char* const char_cases[] = {
- "Google Video",
- "Hello, world\n",
- "0123ABCDwxyz \a\b\t\r\n!+,.~"
- };
-
- static const wchar_t* const wchar_cases[] = {
- L"Google Video",
- L"Hello, world\n",
- L"0123ABCDwxyz \a\b\t\r\n!+,.~"
- };
-
- for (size_t i = 0; i < arraysize(char_cases); ++i) {
- EXPECT_TRUE(IsStringASCII(char_cases[i]));
- string16 utf16 = ASCIIToUTF16(char_cases[i]);
- EXPECT_EQ(WideToUTF16(wchar_cases[i]), utf16);
-
- std::string ascii = UTF16ToASCII(WideToUTF16(wchar_cases[i]));
- EXPECT_EQ(char_cases[i], ascii);
- }
-
- EXPECT_FALSE(IsStringASCII("Google \x80Video"));
-
- // Convert empty strings.
- string16 empty16;
- std::string empty;
- EXPECT_EQ(empty, UTF16ToASCII(empty16));
- EXPECT_EQ(empty16, ASCIIToUTF16(empty));
-
- // Convert strings with an embedded NUL character.
- const char chars_with_nul[] = "test\0string";
- const int length_with_nul = arraysize(chars_with_nul) - 1;
- std::string string_with_nul(chars_with_nul, length_with_nul);
- string16 string16_with_nul = ASCIIToUTF16(string_with_nul);
- EXPECT_EQ(static_cast<string16::size_type>(length_with_nul),
- string16_with_nul.length());
- std::string narrow_with_nul = UTF16ToASCII(string16_with_nul);
- EXPECT_EQ(static_cast<std::string::size_type>(length_with_nul),
- narrow_with_nul.length());
- EXPECT_EQ(0, string_with_nul.compare(narrow_with_nul));
-}
-
-TEST(StringUtilTest, ToLowerASCII) {
- EXPECT_EQ('c', ToLowerASCII('C'));
- EXPECT_EQ('c', ToLowerASCII('c'));
- EXPECT_EQ('2', ToLowerASCII('2'));
-
- EXPECT_EQ(static_cast<char16>('c'), ToLowerASCII(static_cast<char16>('C')));
- EXPECT_EQ(static_cast<char16>('c'), ToLowerASCII(static_cast<char16>('c')));
- EXPECT_EQ(static_cast<char16>('2'), ToLowerASCII(static_cast<char16>('2')));
-
- EXPECT_EQ("cc2", ToLowerASCII("Cc2"));
- EXPECT_EQ(ASCIIToUTF16("cc2"), ToLowerASCII(ASCIIToUTF16("Cc2")));
-}
-
-TEST(StringUtilTest, ToUpperASCII) {
- EXPECT_EQ('C', ToUpperASCII('C'));
- EXPECT_EQ('C', ToUpperASCII('c'));
- EXPECT_EQ('2', ToUpperASCII('2'));
-
- EXPECT_EQ(static_cast<char16>('C'), ToUpperASCII(static_cast<char16>('C')));
- EXPECT_EQ(static_cast<char16>('C'), ToUpperASCII(static_cast<char16>('c')));
- EXPECT_EQ(static_cast<char16>('2'), ToUpperASCII(static_cast<char16>('2')));
-
- EXPECT_EQ("CC2", ToUpperASCII("Cc2"));
- EXPECT_EQ(ASCIIToUTF16("CC2"), ToUpperASCII(ASCIIToUTF16("Cc2")));
-}
-
-TEST(StringUtilTest, LowerCaseEqualsASCII) {
- static const struct {
- const char* src_a;
- const char* dst;
- } lowercase_cases[] = {
- { "FoO", "foo" },
- { "foo", "foo" },
- { "FOO", "foo" },
- };
-
- for (size_t i = 0; i < arraysize(lowercase_cases); ++i) {
- EXPECT_TRUE(LowerCaseEqualsASCII(ASCIIToUTF16(lowercase_cases[i].src_a),
- lowercase_cases[i].dst));
- EXPECT_TRUE(LowerCaseEqualsASCII(lowercase_cases[i].src_a,
- lowercase_cases[i].dst));
- }
-}
-
-TEST(StringUtilTest, FormatBytesUnlocalized) {
- static const struct {
- int64_t bytes;
- const char* expected;
- } cases[] = {
- // Expected behavior: we show one post-decimal digit when we have
- // under two pre-decimal digits, except in cases where it makes no
- // sense (zero or bytes).
- // Since we switch units once we cross the 1000 mark, this keeps
- // the display of file sizes or bytes consistently around three
- // digits.
- {0, "0 B"},
- {512, "512 B"},
- {1024*1024, "1.0 MB"},
- {1024*1024*1024, "1.0 GB"},
- {10LL*1024*1024*1024, "10.0 GB"},
- {99LL*1024*1024*1024, "99.0 GB"},
- {105LL*1024*1024*1024, "105 GB"},
- {105LL*1024*1024*1024 + 500LL*1024*1024, "105 GB"},
- {~(1LL << 63), "8192 PB"},
-
- {99*1024 + 103, "99.1 kB"},
- {1024*1024 + 103, "1.0 MB"},
- {1024*1024 + 205 * 1024, "1.2 MB"},
- {1024*1024*1024 + (927 * 1024*1024), "1.9 GB"},
- {10LL*1024*1024*1024, "10.0 GB"},
- {100LL*1024*1024*1024, "100 GB"},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- EXPECT_EQ(ASCIIToUTF16(cases[i].expected),
- FormatBytesUnlocalized(cases[i].bytes));
- }
-}
-TEST(StringUtilTest, ReplaceSubstringsAfterOffset) {
- static const struct {
- StringPiece str;
- size_t start_offset;
- StringPiece find_this;
- StringPiece replace_with;
- StringPiece expected;
- } cases[] = {
- {"aaa", 0, "", "b", "aaa"},
- {"aaa", 1, "", "b", "aaa"},
- {"aaa", 0, "a", "b", "bbb"},
- {"aaa", 0, "aa", "b", "ba"},
- {"aaa", 0, "aa", "bbb", "bbba"},
- {"aaaaa", 0, "aa", "b", "bba"},
- {"ababaaababa", 0, "aba", "", "baaba"},
- {"ababaaababa", 0, "aba", "_", "_baa_ba"},
- {"ababaaababa", 0, "aba", "__", "__baa__ba"},
- {"ababaaababa", 0, "aba", "___", "___baa___ba"},
- {"ababaaababa", 0, "aba", "____", "____baa____ba"},
- {"ababaaababa", 0, "aba", "_____", "_____baa_____ba"},
- {"abb", 0, "ab", "a", "ab"},
- {"Removing some substrings inging", 0, "ing", "", "Remov some substrs "},
- {"Not found", 0, "x", "0", "Not found"},
- {"Not found again", 5, "x", "0", "Not found again"},
- {" Making it much longer ", 0, " ", "Four score and seven years ago",
- "Four score and seven years agoMakingFour score and seven years agoit"
- "Four score and seven years agomuchFour score and seven years agolonger"
- "Four score and seven years ago"},
- {" Making it much much much much shorter ", 0,
- "Making it much much much much shorter", "", " "},
- {"so much much much much much very much much much shorter", 0, "much ",
- "", "so very shorter"},
- {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
- {"Replace me only me once", 9, "me ", "", "Replace me only once"},
- {"abababab", 2, "ab", "c", "abccc"},
- {"abababab", 1, "ab", "c", "abccc"},
- {"abababab", 1, "aba", "c", "abcbab"},
- };
-
- // base::string16 variant
- for (const auto& scenario : cases) {
- string16 str = ASCIIToUTF16(scenario.str);
- ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
- ASCIIToUTF16(scenario.find_this),
- ASCIIToUTF16(scenario.replace_with));
- EXPECT_EQ(ASCIIToUTF16(scenario.expected), str);
- }
-
- // std::string with insufficient capacity: expansion must realloc the buffer.
- for (const auto& scenario : cases) {
- std::string str = scenario.str.as_string();
- str.shrink_to_fit(); // This is nonbinding, but it's the best we've got.
- ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
- scenario.find_this, scenario.replace_with);
- EXPECT_EQ(scenario.expected, str);
- }
-
- // std::string with ample capacity: should be possible to grow in-place.
- for (const auto& scenario : cases) {
- std::string str = scenario.str.as_string();
- str.reserve(std::max(scenario.str.length(), scenario.expected.length()) *
- 2);
-
- ReplaceSubstringsAfterOffset(&str, scenario.start_offset,
- scenario.find_this, scenario.replace_with);
- EXPECT_EQ(scenario.expected, str);
- }
-}
-
-TEST(StringUtilTest, ReplaceFirstSubstringAfterOffset) {
- static const struct {
- const char* str;
- string16::size_type start_offset;
- const char* find_this;
- const char* replace_with;
- const char* expected;
- } cases[] = {
- {"aaa", 0, "a", "b", "baa"},
- {"abb", 0, "ab", "a", "ab"},
- {"Removing some substrings inging", 0, "ing", "",
- "Remov some substrings inging"},
- {"Not found", 0, "x", "0", "Not found"},
- {"Not found again", 5, "x", "0", "Not found again"},
- {" Making it much longer ", 0, " ", "Four score and seven years ago",
- "Four score and seven years agoMaking it much longer "},
- {"Invalid offset", 9999, "t", "foobar", "Invalid offset"},
- {"Replace me only me once", 4, "me ", "", "Replace only me once"},
- {"abababab", 2, "ab", "c", "abcabab"},
- };
-
- for (size_t i = 0; i < arraysize(cases); i++) {
- string16 str = ASCIIToUTF16(cases[i].str);
- ReplaceFirstSubstringAfterOffset(&str, cases[i].start_offset,
- ASCIIToUTF16(cases[i].find_this),
- ASCIIToUTF16(cases[i].replace_with));
- EXPECT_EQ(ASCIIToUTF16(cases[i].expected), str);
- }
-}
-
-TEST(StringUtilTest, HexDigitToInt) {
- EXPECT_EQ(0, HexDigitToInt('0'));
- EXPECT_EQ(1, HexDigitToInt('1'));
- EXPECT_EQ(2, HexDigitToInt('2'));
- EXPECT_EQ(3, HexDigitToInt('3'));
- EXPECT_EQ(4, HexDigitToInt('4'));
- EXPECT_EQ(5, HexDigitToInt('5'));
- EXPECT_EQ(6, HexDigitToInt('6'));
- EXPECT_EQ(7, HexDigitToInt('7'));
- EXPECT_EQ(8, HexDigitToInt('8'));
- EXPECT_EQ(9, HexDigitToInt('9'));
- EXPECT_EQ(10, HexDigitToInt('A'));
- EXPECT_EQ(11, HexDigitToInt('B'));
- EXPECT_EQ(12, HexDigitToInt('C'));
- EXPECT_EQ(13, HexDigitToInt('D'));
- EXPECT_EQ(14, HexDigitToInt('E'));
- EXPECT_EQ(15, HexDigitToInt('F'));
-
- // Verify the lower case as well.
- EXPECT_EQ(10, HexDigitToInt('a'));
- EXPECT_EQ(11, HexDigitToInt('b'));
- EXPECT_EQ(12, HexDigitToInt('c'));
- EXPECT_EQ(13, HexDigitToInt('d'));
- EXPECT_EQ(14, HexDigitToInt('e'));
- EXPECT_EQ(15, HexDigitToInt('f'));
-}
-
-TEST(StringUtilTest, JoinString) {
- std::string separator(", ");
- std::vector<std::string> parts;
- EXPECT_EQ(std::string(), JoinString(parts, separator));
-
- parts.push_back(std::string());
- EXPECT_EQ(std::string(), JoinString(parts, separator));
- parts.clear();
-
- parts.push_back("a");
- EXPECT_EQ("a", JoinString(parts, separator));
-
- parts.push_back("b");
- parts.push_back("c");
- EXPECT_EQ("a, b, c", JoinString(parts, separator));
-
- parts.push_back(std::string());
- EXPECT_EQ("a, b, c, ", JoinString(parts, separator));
- parts.push_back(" ");
- EXPECT_EQ("a|b|c|| ", JoinString(parts, "|"));
-}
-
-TEST(StringUtilTest, JoinString16) {
- string16 separator = ASCIIToUTF16(", ");
- std::vector<string16> parts;
- EXPECT_EQ(string16(), JoinString(parts, separator));
-
- parts.push_back(string16());
- EXPECT_EQ(string16(), JoinString(parts, separator));
- parts.clear();
-
- parts.push_back(ASCIIToUTF16("a"));
- EXPECT_EQ(ASCIIToUTF16("a"), JoinString(parts, separator));
-
- parts.push_back(ASCIIToUTF16("b"));
- parts.push_back(ASCIIToUTF16("c"));
- EXPECT_EQ(ASCIIToUTF16("a, b, c"), JoinString(parts, separator));
-
- parts.push_back(ASCIIToUTF16(""));
- EXPECT_EQ(ASCIIToUTF16("a, b, c, "), JoinString(parts, separator));
- parts.push_back(ASCIIToUTF16(" "));
- EXPECT_EQ(ASCIIToUTF16("a|b|c|| "), JoinString(parts, ASCIIToUTF16("|")));
-}
-
-TEST(StringUtilTest, JoinStringPiece) {
- std::string separator(", ");
- std::vector<StringPiece> parts;
- EXPECT_EQ(std::string(), JoinString(parts, separator));
-
- // Test empty first part (https://crbug.com/698073).
- parts.push_back(StringPiece());
- EXPECT_EQ(std::string(), JoinString(parts, separator));
- parts.clear();
-
- parts.push_back("a");
- EXPECT_EQ("a", JoinString(parts, separator));
-
- parts.push_back("b");
- parts.push_back("c");
- EXPECT_EQ("a, b, c", JoinString(parts, separator));
-
- parts.push_back(StringPiece());
- EXPECT_EQ("a, b, c, ", JoinString(parts, separator));
- parts.push_back(" ");
- EXPECT_EQ("a|b|c|| ", JoinString(parts, "|"));
-}
-
-TEST(StringUtilTest, JoinStringPiece16) {
- string16 separator = ASCIIToUTF16(", ");
- std::vector<StringPiece16> parts;
- EXPECT_EQ(string16(), JoinString(parts, separator));
-
- // Test empty first part (https://crbug.com/698073).
- parts.push_back(StringPiece16());
- EXPECT_EQ(string16(), JoinString(parts, separator));
- parts.clear();
-
- const string16 kA = ASCIIToUTF16("a");
- parts.push_back(kA);
- EXPECT_EQ(ASCIIToUTF16("a"), JoinString(parts, separator));
-
- const string16 kB = ASCIIToUTF16("b");
- parts.push_back(kB);
- const string16 kC = ASCIIToUTF16("c");
- parts.push_back(kC);
- EXPECT_EQ(ASCIIToUTF16("a, b, c"), JoinString(parts, separator));
-
- parts.push_back(StringPiece16());
- EXPECT_EQ(ASCIIToUTF16("a, b, c, "), JoinString(parts, separator));
- const string16 kSpace = ASCIIToUTF16(" ");
- parts.push_back(kSpace);
- EXPECT_EQ(ASCIIToUTF16("a|b|c|| "), JoinString(parts, ASCIIToUTF16("|")));
-}
-
-TEST(StringUtilTest, JoinStringInitializerList) {
- std::string separator(", ");
- EXPECT_EQ(std::string(), JoinString({}, separator));
-
- // Test empty first part (https://crbug.com/698073).
- EXPECT_EQ(std::string(), JoinString({StringPiece()}, separator));
-
- // With const char*s.
- EXPECT_EQ("a", JoinString({"a"}, separator));
- EXPECT_EQ("a, b, c", JoinString({"a", "b", "c"}, separator));
- EXPECT_EQ("a, b, c, ", JoinString({"a", "b", "c", StringPiece()}, separator));
- EXPECT_EQ("a|b|c|| ", JoinString({"a", "b", "c", StringPiece(), " "}, "|"));
-
- // With std::strings.
- const std::string kA = "a";
- const std::string kB = "b";
- EXPECT_EQ("a, b", JoinString({kA, kB}, separator));
-
- // With StringPieces.
- const StringPiece kPieceA = kA;
- const StringPiece kPieceB = kB;
- EXPECT_EQ("a, b", JoinString({kPieceA, kPieceB}, separator));
-}
-
-TEST(StringUtilTest, JoinStringInitializerList16) {
- string16 separator = ASCIIToUTF16(", ");
- EXPECT_EQ(string16(), JoinString({}, separator));
-
- // Test empty first part (https://crbug.com/698073).
- EXPECT_EQ(string16(), JoinString({StringPiece16()}, separator));
-
- // With string16s.
- const string16 kA = ASCIIToUTF16("a");
- EXPECT_EQ(ASCIIToUTF16("a"), JoinString({kA}, separator));
-
- const string16 kB = ASCIIToUTF16("b");
- const string16 kC = ASCIIToUTF16("c");
- EXPECT_EQ(ASCIIToUTF16("a, b, c"), JoinString({kA, kB, kC}, separator));
-
- EXPECT_EQ(ASCIIToUTF16("a, b, c, "),
- JoinString({kA, kB, kC, StringPiece16()}, separator));
- const string16 kSpace = ASCIIToUTF16(" ");
- EXPECT_EQ(
- ASCIIToUTF16("a|b|c|| "),
- JoinString({kA, kB, kC, StringPiece16(), kSpace}, ASCIIToUTF16("|")));
-
- // With StringPiece16s.
- const StringPiece16 kPieceA = kA;
- const StringPiece16 kPieceB = kB;
- EXPECT_EQ(ASCIIToUTF16("a, b"), JoinString({kPieceA, kPieceB}, separator));
-}
-
-TEST(StringUtilTest, StartsWith) {
- EXPECT_TRUE(StartsWith("javascript:url", "javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith("JavaScript:url", "javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith("javascript:url", "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith("JavaScript:url", "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith("java", "javascript", base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith("java", "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(std::string(), "javascript",
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(std::string(), "javascript",
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith("java", std::string(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith("java", std::string(), base::CompareCase::SENSITIVE));
-
- EXPECT_TRUE(StartsWith(ASCIIToUTF16("javascript:url"),
- ASCIIToUTF16("javascript"),
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith(ASCIIToUTF16("JavaScript:url"),
- ASCIIToUTF16("javascript"),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith(ASCIIToUTF16("javascript:url"),
- ASCIIToUTF16("javascript"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith(ASCIIToUTF16("JavaScript:url"),
- ASCIIToUTF16("javascript"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(ASCIIToUTF16("java"), ASCIIToUTF16("javascript"),
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(StartsWith(ASCIIToUTF16("java"), ASCIIToUTF16("javascript"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(string16(), ASCIIToUTF16("javascript"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(StartsWith(string16(), ASCIIToUTF16("javascript"),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(StartsWith(ASCIIToUTF16("java"), string16(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(StartsWith(ASCIIToUTF16("java"), string16(),
- base::CompareCase::SENSITIVE));
-}
-
-TEST(StringUtilTest, EndsWith) {
- EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), ASCIIToUTF16(".plugin"),
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.Plugin"), ASCIIToUTF16(".plugin"),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), ASCIIToUTF16(".plugin"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.Plugin"), ASCIIToUTF16(".plugin"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(EndsWith(ASCIIToUTF16(".plug"), ASCIIToUTF16(".plugin"),
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(EndsWith(ASCIIToUTF16(".plug"), ASCIIToUTF16(".plugin"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.plugin Bar"), ASCIIToUTF16(".plugin"),
- base::CompareCase::SENSITIVE));
- EXPECT_FALSE(EndsWith(ASCIIToUTF16("Foo.plugin Bar"), ASCIIToUTF16(".plugin"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(EndsWith(string16(), ASCIIToUTF16(".plugin"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_FALSE(EndsWith(string16(), ASCIIToUTF16(".plugin"),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), string16(),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(ASCIIToUTF16("Foo.plugin"), string16(),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(EndsWith(ASCIIToUTF16(".plugin"), ASCIIToUTF16(".plugin"),
- base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(ASCIIToUTF16(".plugin"), ASCIIToUTF16(".plugin"),
- base::CompareCase::SENSITIVE));
- EXPECT_TRUE(
- EndsWith(string16(), string16(), base::CompareCase::INSENSITIVE_ASCII));
- EXPECT_TRUE(EndsWith(string16(), string16(), base::CompareCase::SENSITIVE));
-}
-
-TEST(StringUtilTest, GetStringFWithOffsets) {
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("1"));
- subst.push_back(ASCIIToUTF16("2"));
- std::vector<size_t> offsets;
-
- ReplaceStringPlaceholders(ASCIIToUTF16("Hello, $1. Your number is $2."),
- subst,
- &offsets);
- EXPECT_EQ(2U, offsets.size());
- EXPECT_EQ(7U, offsets[0]);
- EXPECT_EQ(25U, offsets[1]);
- offsets.clear();
-
- ReplaceStringPlaceholders(ASCIIToUTF16("Hello, $2. Your number is $1."),
- subst,
- &offsets);
- EXPECT_EQ(2U, offsets.size());
- EXPECT_EQ(25U, offsets[0]);
- EXPECT_EQ(7U, offsets[1]);
- offsets.clear();
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholdersTooFew) {
- // Test whether replacestringplaceholders works as expected when there
- // are fewer inputs than outputs.
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("9a"));
- subst.push_back(ASCIIToUTF16("8b"));
- subst.push_back(ASCIIToUTF16("7c"));
-
- string16 formatted =
- ReplaceStringPlaceholders(
- ASCIIToUTF16("$1a,$2b,$3c,$4d,$5e,$6f,$1g,$2h,$3i"), subst, nullptr);
-
- EXPECT_EQ(ASCIIToUTF16("9aa,8bb,7cc,d,e,f,9ag,8bh,7ci"), formatted);
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholders) {
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("9a"));
- subst.push_back(ASCIIToUTF16("8b"));
- subst.push_back(ASCIIToUTF16("7c"));
- subst.push_back(ASCIIToUTF16("6d"));
- subst.push_back(ASCIIToUTF16("5e"));
- subst.push_back(ASCIIToUTF16("4f"));
- subst.push_back(ASCIIToUTF16("3g"));
- subst.push_back(ASCIIToUTF16("2h"));
- subst.push_back(ASCIIToUTF16("1i"));
-
- string16 formatted =
- ReplaceStringPlaceholders(
- ASCIIToUTF16("$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i"), subst, nullptr);
-
- EXPECT_EQ(ASCIIToUTF16("9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii"), formatted);
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholdersNetExpansionWithContraction) {
- // In this test, some of the substitutions are shorter than the placeholders,
- // but overall the string gets longer.
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("9a____"));
- subst.push_back(ASCIIToUTF16("B"));
- subst.push_back(ASCIIToUTF16("7c___"));
- subst.push_back(ASCIIToUTF16("d"));
- subst.push_back(ASCIIToUTF16("5e____"));
- subst.push_back(ASCIIToUTF16("F"));
- subst.push_back(ASCIIToUTF16("3g___"));
- subst.push_back(ASCIIToUTF16("h"));
- subst.push_back(ASCIIToUTF16("1i_____"));
-
- string16 original = ASCIIToUTF16("$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i");
- string16 expected =
- ASCIIToUTF16("9a____a,Bb,7c___c,dd,5e____e,Ff,3g___g,hh,1i_____i");
-
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, nullptr));
-
- std::vector<size_t> offsets;
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, &offsets));
- std::vector<size_t> expected_offsets = {0, 8, 11, 18, 21, 29, 32, 39, 42};
- EXPECT_EQ(offsets.size(), subst.size());
- EXPECT_EQ(expected_offsets, offsets);
- for (size_t i = 0; i < offsets.size(); i++) {
- EXPECT_EQ(expected.substr(expected_offsets[i], subst[i].length()),
- subst[i]);
- }
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholdersNetContractionWithExpansion) {
- // In this test, some of the substitutions are longer than the placeholders,
- // but overall the string gets smaller. Additionally, the placeholders appear
- // in a permuted order.
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("z"));
- subst.push_back(ASCIIToUTF16("y"));
- subst.push_back(ASCIIToUTF16("XYZW"));
- subst.push_back(ASCIIToUTF16("x"));
- subst.push_back(ASCIIToUTF16("w"));
-
- string16 formatted =
- ReplaceStringPlaceholders(ASCIIToUTF16("$3_$4$2$1$5"), subst, nullptr);
-
- EXPECT_EQ(ASCIIToUTF16("XYZW_xyzw"), formatted);
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholdersOneDigit) {
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("1a"));
- string16 formatted =
- ReplaceStringPlaceholders(ASCIIToUTF16(" $16 "), subst, nullptr);
- EXPECT_EQ(ASCIIToUTF16(" 1a6 "), formatted);
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholdersInvalidPlaceholder) {
- std::vector<string16> subst;
- subst.push_back(ASCIIToUTF16("1a"));
- string16 formatted =
- ReplaceStringPlaceholders(ASCIIToUTF16("+$-+$A+$1+"), subst, nullptr);
- EXPECT_EQ(ASCIIToUTF16("+++1a+"), formatted);
-}
-
-TEST(StringUtilTest, StdStringReplaceStringPlaceholders) {
- std::vector<std::string> subst;
- subst.push_back("9a");
- subst.push_back("8b");
- subst.push_back("7c");
- subst.push_back("6d");
- subst.push_back("5e");
- subst.push_back("4f");
- subst.push_back("3g");
- subst.push_back("2h");
- subst.push_back("1i");
-
- std::string formatted =
- ReplaceStringPlaceholders(
- "$1a,$2b,$3c,$4d,$5e,$6f,$7g,$8h,$9i", subst, nullptr);
-
- EXPECT_EQ("9aa,8bb,7cc,6dd,5ee,4ff,3gg,2hh,1ii", formatted);
-}
-
-TEST(StringUtilTest, StdStringReplaceStringPlaceholdersMultipleMatches) {
- std::vector<std::string> subst;
- subst.push_back("4"); // Referenced twice.
- subst.push_back("?"); // Unreferenced.
- subst.push_back("!"); // Unreferenced.
- subst.push_back("16"); // Referenced once.
-
- std::string original = "$1 * $1 == $4";
- std::string expected = "4 * 4 == 16";
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, nullptr));
- std::vector<size_t> offsets;
- EXPECT_EQ(expected, ReplaceStringPlaceholders(original, subst, &offsets));
- std::vector<size_t> expected_offsets = {0, 4, 9};
- EXPECT_EQ(expected_offsets, offsets);
-}
-
-TEST(StringUtilTest, ReplaceStringPlaceholdersConsecutiveDollarSigns) {
- std::vector<std::string> subst;
- subst.push_back("a");
- subst.push_back("b");
- subst.push_back("c");
- EXPECT_EQ(ReplaceStringPlaceholders("$$1 $$$2 $$$$3", subst, nullptr),
- "$1 $$2 $$$3");
-}
-
-TEST(StringUtilTest, LcpyTest) {
- // Test the normal case where we fit in our buffer.
- {
- char dst[10];
- wchar_t wdst[10];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", arraysize(dst)));
- EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
- }
-
- // Test dst_size == 0, nothing should be written to |dst| and we should
- // have the equivalent of strlen(src).
- {
- char dst[2] = {1, 2};
- wchar_t wdst[2] = {1, 2};
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", 0));
- EXPECT_EQ(1, dst[0]);
- EXPECT_EQ(2, dst[1]);
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", 0));
- EXPECT_EQ(static_cast<wchar_t>(1), wdst[0]);
- EXPECT_EQ(static_cast<wchar_t>(2), wdst[1]);
- }
-
- // Test the case were we _just_ competely fit including the null.
- {
- char dst[8];
- wchar_t wdst[8];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", arraysize(dst)));
- EXPECT_EQ(0, memcmp(dst, "abcdefg", 8));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"abcdefg", sizeof(wchar_t) * 8));
- }
-
- // Test the case were we we are one smaller, so we can't fit the null.
- {
- char dst[7];
- wchar_t wdst[7];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", arraysize(dst)));
- EXPECT_EQ(0, memcmp(dst, "abcdef", 7));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"abcdef", sizeof(wchar_t) * 7));
- }
-
- // Test the case were we are just too small.
- {
- char dst[3];
- wchar_t wdst[3];
- EXPECT_EQ(7U, strlcpy(dst, "abcdefg", arraysize(dst)));
- EXPECT_EQ(0, memcmp(dst, "ab", 3));
- EXPECT_EQ(7U, wcslcpy(wdst, L"abcdefg", arraysize(wdst)));
- EXPECT_EQ(0, memcmp(wdst, L"ab", sizeof(wchar_t) * 3));
- }
-}
-
-TEST(StringUtilTest, WprintfFormatPortabilityTest) {
- static const struct {
- const wchar_t* input;
- bool portable;
- } cases[] = {
- { L"%ls", true },
- { L"%s", false },
- { L"%S", false },
- { L"%lS", false },
- { L"Hello, %s", false },
- { L"%lc", true },
- { L"%c", false },
- { L"%C", false },
- { L"%lC", false },
- { L"%ls %s", false },
- { L"%s %ls", false },
- { L"%s %ls %s", false },
- { L"%f", true },
- { L"%f %F", false },
- { L"%d %D", false },
- { L"%o %O", false },
- { L"%u %U", false },
- { L"%f %d %o %u", true },
- { L"%-8d (%02.1f%)", true },
- { L"% 10s", false },
- { L"% 10ls", true }
- };
- for (size_t i = 0; i < arraysize(cases); ++i)
- EXPECT_EQ(cases[i].portable, IsWprintfFormatPortable(cases[i].input));
-}
-
-TEST(StringUtilTest, RemoveChars) {
- const char kRemoveChars[] = "-/+*";
- std::string input = "A-+bc/d!*";
- EXPECT_TRUE(RemoveChars(input, kRemoveChars, &input));
- EXPECT_EQ("Abcd!", input);
-
- // No characters match kRemoveChars.
- EXPECT_FALSE(RemoveChars(input, kRemoveChars, &input));
- EXPECT_EQ("Abcd!", input);
-
- // Empty string.
- input.clear();
- EXPECT_FALSE(RemoveChars(input, kRemoveChars, &input));
- EXPECT_EQ(std::string(), input);
-}
-
-TEST(StringUtilTest, ReplaceChars) {
- struct TestData {
- const char* input;
- const char* replace_chars;
- const char* replace_with;
- const char* output;
- bool result;
- } cases[] = {
- {"", "", "", "", false},
- {"t", "t", "t", "t", true},
- {"a", "b", "c", "a", false},
- {"b", "b", "c", "c", true},
- {"bob", "b", "p", "pop", true},
- {"bob", "o", "i", "bib", true},
- {"test", "", "", "test", false},
- {"test", "", "!", "test", false},
- {"test", "z", "!", "test", false},
- {"test", "e", "!", "t!st", true},
- {"test", "e", "!?", "t!?st", true},
- {"test", "ez", "!", "t!st", true},
- {"test", "zed", "!?", "t!?st", true},
- {"test", "t", "!?", "!?es!?", true},
- {"test", "et", "!>", "!>!>s!>", true},
- {"test", "zest", "!", "!!!!", true},
- {"test", "szt", "!", "!e!!", true},
- {"test", "t", "test", "testestest", true},
- {"tetst", "t", "test", "testeteststest", true},
- {"ttttttt", "t", "-", "-------", true},
- {"aAaAaAAaAAa", "A", "", "aaaaa", true},
- {"xxxxxxxxxx", "x", "", "", true},
- {"xxxxxxxxxx", "x", "x", "xxxxxxxxxx", true},
- {"xxxxxxxxxx", "x", "y-", "y-y-y-y-y-y-y-y-y-y-", true},
- {"xxxxxxxxxx", "x", "xy", "xyxyxyxyxyxyxyxyxyxy", true},
- {"xxxxxxxxxx", "x", "zyx", "zyxzyxzyxzyxzyxzyxzyxzyxzyxzyx", true},
- {"xaxxaxxxaxxxax", "x", "xy", "xyaxyxyaxyxyxyaxyxyxyaxy", true},
- {"-xaxxaxxxaxxxax-", "x", "xy", "-xyaxyxyaxyxyxyaxyxyxyaxy-", true},
- };
-
- for (const TestData& scenario : cases) {
- // Test with separate output and input vars.
- std::string output;
- bool result = ReplaceChars(scenario.input, scenario.replace_chars,
- scenario.replace_with, &output);
- EXPECT_EQ(scenario.result, result) << scenario.input;
- EXPECT_EQ(scenario.output, output);
- }
-
- for (const TestData& scenario : cases) {
- // Test with an input/output var of limited capacity.
- std::string input_output = scenario.input;
- input_output.shrink_to_fit();
- bool result = ReplaceChars(input_output, scenario.replace_chars,
- scenario.replace_with, &input_output);
- EXPECT_EQ(scenario.result, result) << scenario.input;
- EXPECT_EQ(scenario.output, input_output);
- }
-
- for (const TestData& scenario : cases) {
- // Test with an input/output var of ample capacity; should
- // not realloc.
- std::string input_output = scenario.input;
- input_output.reserve(strlen(scenario.output) * 2);
- const void* original_buffer = input_output.data();
- bool result = ReplaceChars(input_output, scenario.replace_chars,
- scenario.replace_with, &input_output);
- EXPECT_EQ(scenario.result, result) << scenario.input;
- EXPECT_EQ(scenario.output, input_output);
- EXPECT_EQ(original_buffer, input_output.data());
- }
-}
-
-TEST(StringUtilTest, ContainsOnlyChars) {
- // Providing an empty list of characters should return false but for the empty
- // string.
- EXPECT_TRUE(ContainsOnlyChars(std::string(), std::string()));
- EXPECT_FALSE(ContainsOnlyChars("Hello", std::string()));
-
- EXPECT_TRUE(ContainsOnlyChars(std::string(), "1234"));
- EXPECT_TRUE(ContainsOnlyChars("1", "1234"));
- EXPECT_TRUE(ContainsOnlyChars("1", "4321"));
- EXPECT_TRUE(ContainsOnlyChars("123", "4321"));
- EXPECT_FALSE(ContainsOnlyChars("123a", "4321"));
-
- EXPECT_TRUE(ContainsOnlyChars(std::string(), kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars(" ", kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars("\t", kWhitespaceASCII));
- EXPECT_TRUE(ContainsOnlyChars("\t \r \n ", kWhitespaceASCII));
- EXPECT_FALSE(ContainsOnlyChars("a", kWhitespaceASCII));
- EXPECT_FALSE(ContainsOnlyChars("\thello\r \n ", kWhitespaceASCII));
-
- EXPECT_TRUE(ContainsOnlyChars(string16(), kWhitespaceUTF16));
- EXPECT_TRUE(ContainsOnlyChars(ASCIIToUTF16(" "), kWhitespaceUTF16));
- EXPECT_TRUE(ContainsOnlyChars(ASCIIToUTF16("\t"), kWhitespaceUTF16));
- EXPECT_TRUE(ContainsOnlyChars(ASCIIToUTF16("\t \r \n "), kWhitespaceUTF16));
- EXPECT_FALSE(ContainsOnlyChars(ASCIIToUTF16("a"), kWhitespaceUTF16));
- EXPECT_FALSE(ContainsOnlyChars(ASCIIToUTF16("\thello\r \n "),
- kWhitespaceUTF16));
-}
-
-TEST(StringUtilTest, CompareCaseInsensitiveASCII) {
- EXPECT_EQ(0, CompareCaseInsensitiveASCII("", ""));
- EXPECT_EQ(0, CompareCaseInsensitiveASCII("Asdf", "aSDf"));
-
- // Differing lengths.
- EXPECT_EQ(-1, CompareCaseInsensitiveASCII("Asdf", "aSDfA"));
- EXPECT_EQ(1, CompareCaseInsensitiveASCII("AsdfA", "aSDf"));
-
- // Differing values.
- EXPECT_EQ(-1, CompareCaseInsensitiveASCII("AsdfA", "aSDfb"));
- EXPECT_EQ(1, CompareCaseInsensitiveASCII("Asdfb", "aSDfA"));
-}
-
-TEST(StringUtilTest, EqualsCaseInsensitiveASCII) {
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("", ""));
- EXPECT_TRUE(EqualsCaseInsensitiveASCII("Asdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("bsdf", "aSDF"));
- EXPECT_FALSE(EqualsCaseInsensitiveASCII("Asdf", "aSDFz"));
-}
-
-TEST(StringUtilTest, IsUnicodeWhitespace) {
- // NOT unicode white space.
- EXPECT_FALSE(IsUnicodeWhitespace(L'\0'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'A'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'0'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'.'));
- EXPECT_FALSE(IsUnicodeWhitespace(L';'));
- EXPECT_FALSE(IsUnicodeWhitespace(L'\x4100'));
-
- // Actual unicode whitespace.
- EXPECT_TRUE(IsUnicodeWhitespace(L' '));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\xa0'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\x3000'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\t'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\r'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\v'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\f'));
- EXPECT_TRUE(IsUnicodeWhitespace(L'\n'));
-}
-
-class WriteIntoTest : public testing::Test {
- protected:
- static void WritesCorrectly(size_t num_chars) {
- std::string buffer;
- char kOriginal[] = "supercali";
- strncpy(WriteInto(&buffer, num_chars + 1), kOriginal, num_chars);
- // Using std::string(buffer.c_str()) instead of |buffer| truncates the
- // string at the first \0.
- EXPECT_EQ(std::string(kOriginal,
- std::min(num_chars, arraysize(kOriginal) - 1)),
- std::string(buffer.c_str()));
- EXPECT_EQ(num_chars, buffer.size());
- }
-};
-
-TEST_F(WriteIntoTest, WriteInto) {
- // Validate that WriteInto reserves enough space and
- // sizes a string correctly.
- WritesCorrectly(1);
- WritesCorrectly(2);
- WritesCorrectly(5000);
-
- // Validate that WriteInto doesn't modify other strings
- // when using a Copy-on-Write implementation.
- const char kLive[] = "live";
- const char kDead[] = "dead";
- const std::string live = kLive;
- std::string dead = live;
- strncpy(WriteInto(&dead, 5), kDead, 4);
- EXPECT_EQ(kDead, dead);
- EXPECT_EQ(4u, dead.size());
- EXPECT_EQ(kLive, live);
- EXPECT_EQ(4u, live.size());
-}
-
-} // namespace base
diff --git a/base/strings/stringize_macros_unittest.cc b/base/strings/stringize_macros_unittest.cc
deleted file mode 100644
index d7f9e56..0000000
--- a/base/strings/stringize_macros_unittest.cc
+++ /dev/null
@@ -1,29 +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/strings/stringize_macros.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-// Macros as per documentation in header file.
-#define PREPROCESSOR_UTIL_UNITTEST_A FOO
-#define PREPROCESSOR_UTIL_UNITTEST_B(x) myobj->FunctionCall(x)
-#define PREPROCESSOR_UTIL_UNITTEST_C "foo"
-
-TEST(StringizeTest, Ansi) {
- EXPECT_STREQ(
- "PREPROCESSOR_UTIL_UNITTEST_A",
- STRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_A));
- EXPECT_STREQ(
- "PREPROCESSOR_UTIL_UNITTEST_B(y)",
- STRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_B(y)));
- EXPECT_STREQ(
- "PREPROCESSOR_UTIL_UNITTEST_C",
- STRINGIZE_NO_EXPANSION(PREPROCESSOR_UTIL_UNITTEST_C));
-
- EXPECT_STREQ("FOO", STRINGIZE(PREPROCESSOR_UTIL_UNITTEST_A));
- EXPECT_STREQ("myobj->FunctionCall(y)",
- STRINGIZE(PREPROCESSOR_UTIL_UNITTEST_B(y)));
- EXPECT_STREQ("\"foo\"", STRINGIZE(PREPROCESSOR_UTIL_UNITTEST_C));
-}
diff --git a/base/strings/stringprintf_unittest.cc b/base/strings/stringprintf_unittest.cc
deleted file mode 100644
index 02cd349..0000000
--- a/base/strings/stringprintf_unittest.cc
+++ /dev/null
@@ -1,182 +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/stringprintf.h"
-
-#include <errno.h>
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// A helper for the StringAppendV test that follows.
-//
-// Just forwards its args to StringAppendV.
-static void StringAppendVTestHelper(std::string* out, const char* format, ...) {
- va_list ap;
- va_start(ap, format);
- StringAppendV(out, format, ap);
- va_end(ap);
-}
-
-} // namespace
-
-TEST(StringPrintfTest, StringPrintfEmpty) {
- EXPECT_EQ("", StringPrintf("%s", ""));
-}
-
-TEST(StringPrintfTest, StringPrintfMisc) {
- EXPECT_EQ("123hello w", StringPrintf("%3d%2s %1c", 123, "hello", 'w'));
-#if defined(OS_WIN)
- EXPECT_EQ(L"123hello w", StringPrintf(L"%3d%2ls %1lc", 123, L"hello", 'w'));
-#endif
-}
-
-TEST(StringPrintfTest, StringAppendfEmptyString) {
- std::string value("Hello");
- StringAppendF(&value, "%s", "");
- EXPECT_EQ("Hello", value);
-
-#if defined(OS_WIN)
- std::wstring valuew(L"Hello");
- StringAppendF(&valuew, L"%ls", L"");
- EXPECT_EQ(L"Hello", valuew);
-#endif
-}
-
-TEST(StringPrintfTest, StringAppendfString) {
- std::string value("Hello");
- StringAppendF(&value, " %s", "World");
- EXPECT_EQ("Hello World", value);
-
-#if defined(OS_WIN)
- std::wstring valuew(L"Hello");
- StringAppendF(&valuew, L" %ls", L"World");
- EXPECT_EQ(L"Hello World", valuew);
-#endif
-}
-
-TEST(StringPrintfTest, StringAppendfInt) {
- std::string value("Hello");
- StringAppendF(&value, " %d", 123);
- EXPECT_EQ("Hello 123", value);
-
-#if defined(OS_WIN)
- std::wstring valuew(L"Hello");
- StringAppendF(&valuew, L" %d", 123);
- EXPECT_EQ(L"Hello 123", valuew);
-#endif
-}
-
-// Make sure that lengths exactly around the initial buffer size are handled
-// correctly.
-TEST(StringPrintfTest, StringPrintfBounds) {
- const int kSrcLen = 1026;
- char src[kSrcLen];
- for (size_t i = 0; i < arraysize(src); i++)
- src[i] = 'A';
-
- wchar_t srcw[kSrcLen];
- for (size_t i = 0; i < arraysize(srcw); i++)
- srcw[i] = 'A';
-
- for (int i = 1; i < 3; i++) {
- src[kSrcLen - i] = 0;
- std::string out;
- SStringPrintf(&out, "%s", src);
- EXPECT_STREQ(src, out.c_str());
-
-#if defined(OS_WIN)
- srcw[kSrcLen - i] = 0;
- std::wstring outw;
- SStringPrintf(&outw, L"%ls", srcw);
- EXPECT_STREQ(srcw, outw.c_str());
-#endif
- }
-}
-
-// Test very large sprintfs that will cause the buffer to grow.
-TEST(StringPrintfTest, Grow) {
- char src[1026];
- for (size_t i = 0; i < arraysize(src); i++)
- src[i] = 'A';
- src[1025] = 0;
-
- const char fmt[] = "%sB%sB%sB%sB%sB%sB%s";
-
- std::string out;
- SStringPrintf(&out, fmt, src, src, src, src, src, src, src);
-
- const int kRefSize = 320000;
- char* ref = new char[kRefSize];
-#if defined(OS_WIN)
- sprintf_s(ref, kRefSize, fmt, src, src, src, src, src, src, src);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- snprintf(ref, kRefSize, fmt, src, src, src, src, src, src, src);
-#endif
-
- EXPECT_STREQ(ref, out.c_str());
- delete[] ref;
-}
-
-TEST(StringPrintfTest, StringAppendV) {
- std::string out;
- StringAppendVTestHelper(&out, "%d foo %s", 1, "bar");
- EXPECT_EQ("1 foo bar", out);
-}
-
-// Test the boundary condition for the size of the string_util's
-// internal buffer.
-TEST(StringPrintfTest, GrowBoundary) {
- const int kStringUtilBufLen = 1024;
- // Our buffer should be one larger than the size of StringAppendVT's stack
- // buffer.
- // And need extra one for NULL-terminator.
- const int kBufLen = kStringUtilBufLen + 1 + 1;
- char src[kBufLen];
- for (int i = 0; i < kBufLen - 1; ++i)
- src[i] = 'a';
- src[kBufLen - 1] = 0;
-
- std::string out;
- SStringPrintf(&out, "%s", src);
-
- EXPECT_STREQ(src, out.c_str());
-}
-
-#if defined(OS_WIN)
-// vswprintf in Visual Studio 2013 fails when given U+FFFF. This tests that the
-// failure case is gracefuly handled. In Visual Studio 2015 the bad character
-// is passed through.
-TEST(StringPrintfTest, Invalid) {
- wchar_t invalid[2];
- invalid[0] = 0xffff;
- invalid[1] = 0;
-
- std::wstring out;
- SStringPrintf(&out, L"%ls", invalid);
-#if _MSC_VER >= 1900
- EXPECT_STREQ(invalid, out.c_str());
-#else
- EXPECT_STREQ(L"", out.c_str());
-#endif
-}
-#endif
-
-// Test that StringPrintf and StringAppendV do not change errno.
-TEST(StringPrintfTest, StringPrintfErrno) {
- errno = 1;
- EXPECT_EQ("", StringPrintf("%s", ""));
- EXPECT_EQ(1, errno);
- std::string out;
- StringAppendVTestHelper(&out, "%d foo %s", 1, "bar");
- EXPECT_EQ(1, errno);
-}
-
-} // namespace base
diff --git a/base/strings/sys_string_conversions_unittest.cc b/base/strings/sys_string_conversions_unittest.cc
deleted file mode 100644
index 0f4eddd..0000000
--- a/base/strings/sys_string_conversions_unittest.cc
+++ /dev/null
@@ -1,196 +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/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/sys_string_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/test/scoped_locale.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#ifdef WCHAR_T_IS_UTF32
-static const std::wstring kSysWideOldItalicLetterA = L"\x10300";
-#else
-static const std::wstring kSysWideOldItalicLetterA = L"\xd800\xdf00";
-#endif
-
-namespace base {
-
-TEST(SysStrings, SysWideToUTF8) {
- EXPECT_EQ("Hello, world", SysWideToUTF8(L"Hello, world"));
- EXPECT_EQ("\xe4\xbd\xa0\xe5\xa5\xbd", SysWideToUTF8(L"\x4f60\x597d"));
-
- // >16 bits
- EXPECT_EQ("\xF0\x90\x8C\x80", SysWideToUTF8(kSysWideOldItalicLetterA));
-
- // Error case. When Windows finds a UTF-16 character going off the end of
- // a string, it just converts that literal value to UTF-8, even though this
- // is invalid.
- //
- // This is what XP does, but Vista has different behavior, so we don't bother
- // verifying it:
- // EXPECT_EQ("\xE4\xBD\xA0\xED\xA0\x80zyxw",
- // SysWideToUTF8(L"\x4f60\xd800zyxw"));
-
- // Test embedded NULLs.
- std::wstring wide_null(L"a");
- wide_null.push_back(0);
- wide_null.push_back('b');
-
- std::string expected_null("a");
- expected_null.push_back(0);
- expected_null.push_back('b');
-
- EXPECT_EQ(expected_null, SysWideToUTF8(wide_null));
-}
-
-TEST(SysStrings, SysUTF8ToWide) {
- EXPECT_EQ(L"Hello, world", SysUTF8ToWide("Hello, world"));
- EXPECT_EQ(L"\x4f60\x597d", SysUTF8ToWide("\xe4\xbd\xa0\xe5\xa5\xbd"));
- // >16 bits
- EXPECT_EQ(kSysWideOldItalicLetterA, SysUTF8ToWide("\xF0\x90\x8C\x80"));
-
- // Error case. When Windows finds an invalid UTF-8 character, it just skips
- // it. This seems weird because it's inconsistent with the reverse conversion.
- //
- // This is what XP does, but Vista has different behavior, so we don't bother
- // verifying it:
- // EXPECT_EQ(L"\x4f60zyxw", SysUTF8ToWide("\xe4\xbd\xa0\xe5\xa5zyxw"));
-
- // Test embedded NULLs.
- std::string utf8_null("a");
- utf8_null.push_back(0);
- utf8_null.push_back('b');
-
- std::wstring expected_null(L"a");
- expected_null.push_back(0);
- expected_null.push_back('b');
-
- EXPECT_EQ(expected_null, SysUTF8ToWide(utf8_null));
-}
-
-#if defined(OS_LINUX) // Tests depend on setting a specific Linux locale.
-
-TEST(SysStrings, SysWideToNativeMB) {
-#if !defined(SYSTEM_NATIVE_UTF8)
- ScopedLocale locale("en_US.UTF-8");
-#endif
- EXPECT_EQ("Hello, world", SysWideToNativeMB(L"Hello, world"));
- EXPECT_EQ("\xe4\xbd\xa0\xe5\xa5\xbd", SysWideToNativeMB(L"\x4f60\x597d"));
-
- // >16 bits
- EXPECT_EQ("\xF0\x90\x8C\x80", SysWideToNativeMB(kSysWideOldItalicLetterA));
-
- // Error case. When Windows finds a UTF-16 character going off the end of
- // a string, it just converts that literal value to UTF-8, even though this
- // is invalid.
- //
- // This is what XP does, but Vista has different behavior, so we don't bother
- // verifying it:
- // EXPECT_EQ("\xE4\xBD\xA0\xED\xA0\x80zyxw",
- // SysWideToNativeMB(L"\x4f60\xd800zyxw"));
-
- // Test embedded NULLs.
- std::wstring wide_null(L"a");
- wide_null.push_back(0);
- wide_null.push_back('b');
-
- std::string expected_null("a");
- expected_null.push_back(0);
- expected_null.push_back('b');
-
- EXPECT_EQ(expected_null, SysWideToNativeMB(wide_null));
-}
-
-// We assume the test is running in a UTF8 locale.
-TEST(SysStrings, SysNativeMBToWide) {
-#if !defined(SYSTEM_NATIVE_UTF8)
- ScopedLocale locale("en_US.UTF-8");
-#endif
- EXPECT_EQ(L"Hello, world", SysNativeMBToWide("Hello, world"));
- EXPECT_EQ(L"\x4f60\x597d", SysNativeMBToWide("\xe4\xbd\xa0\xe5\xa5\xbd"));
- // >16 bits
- EXPECT_EQ(kSysWideOldItalicLetterA, SysNativeMBToWide("\xF0\x90\x8C\x80"));
-
- // Error case. When Windows finds an invalid UTF-8 character, it just skips
- // it. This seems weird because it's inconsistent with the reverse conversion.
- //
- // This is what XP does, but Vista has different behavior, so we don't bother
- // verifying it:
- // EXPECT_EQ(L"\x4f60zyxw", SysNativeMBToWide("\xe4\xbd\xa0\xe5\xa5zyxw"));
-
- // Test embedded NULLs.
- std::string utf8_null("a");
- utf8_null.push_back(0);
- utf8_null.push_back('b');
-
- std::wstring expected_null(L"a");
- expected_null.push_back(0);
- expected_null.push_back('b');
-
- EXPECT_EQ(expected_null, SysNativeMBToWide(utf8_null));
-}
-
-static const wchar_t* const kConvertRoundtripCases[] = {
- L"Google Video",
- // "网页 图片 资讯更多 »"
- L"\x7f51\x9875\x0020\x56fe\x7247\x0020\x8d44\x8baf\x66f4\x591a\x0020\x00bb",
- // "Παγκόσμιος Ιστός"
- L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2",
- // "Поиск страниц на русском"
- L"\x041f\x043e\x0438\x0441\x043a\x0020\x0441\x0442"
- L"\x0440\x0430\x043d\x0438\x0446\x0020\x043d\x0430"
- L"\x0020\x0440\x0443\x0441\x0441\x043a\x043e\x043c",
- // "전체서비스"
- L"\xc804\xccb4\xc11c\xbe44\xc2a4",
-
- // Test characters that take more than 16 bits. This will depend on whether
- // wchar_t is 16 or 32 bits.
-#if defined(WCHAR_T_IS_UTF16)
- L"\xd800\xdf00",
- // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E)
- L"\xd807\xdd40\xd807\xdd41\xd807\xdd42\xd807\xdd43\xd807\xdd44",
-#elif defined(WCHAR_T_IS_UTF32)
- L"\x10300",
- // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E)
- L"\x11d40\x11d41\x11d42\x11d43\x11d44",
-#endif
-};
-
-
-TEST(SysStrings, SysNativeMBAndWide) {
-#if !defined(SYSTEM_NATIVE_UTF8)
- ScopedLocale locale("en_US.UTF-8");
-#endif
- for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) {
- std::wstring wide = kConvertRoundtripCases[i];
- std::wstring trip = SysNativeMBToWide(SysWideToNativeMB(wide));
- EXPECT_EQ(wide.size(), trip.size());
- EXPECT_EQ(wide, trip);
- }
-
- // We assume our test is running in UTF-8, so double check through ICU.
- for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) {
- std::wstring wide = kConvertRoundtripCases[i];
- std::wstring trip = SysNativeMBToWide(WideToUTF8(wide));
- EXPECT_EQ(wide.size(), trip.size());
- EXPECT_EQ(wide, trip);
- }
-
- for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) {
- std::wstring wide = kConvertRoundtripCases[i];
- std::wstring trip = UTF8ToWide(SysWideToNativeMB(wide));
- EXPECT_EQ(wide.size(), trip.size());
- EXPECT_EQ(wide, trip);
- }
-}
-#endif // OS_LINUX
-
-} // namespace base
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 c5ce647..0000000
--- 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/strings/utf_string_conversions_unittest.cc b/base/strings/utf_string_conversions_unittest.cc
deleted file mode 100644
index ce776c8..0000000
--- a/base/strings/utf_string_conversions_unittest.cc
+++ /dev/null
@@ -1,211 +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 <stddef.h>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/string_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-const wchar_t* const kConvertRoundtripCases[] = {
- L"Google Video",
- // "网页 图片 资讯更多 »"
- L"\x7f51\x9875\x0020\x56fe\x7247\x0020\x8d44\x8baf\x66f4\x591a\x0020\x00bb",
- // "Παγκόσμιος Ιστός"
- L"\x03a0\x03b1\x03b3\x03ba\x03cc\x03c3\x03bc\x03b9"
- L"\x03bf\x03c2\x0020\x0399\x03c3\x03c4\x03cc\x03c2",
- // "Поиск страниц на русском"
- L"\x041f\x043e\x0438\x0441\x043a\x0020\x0441\x0442"
- L"\x0440\x0430\x043d\x0438\x0446\x0020\x043d\x0430"
- L"\x0020\x0440\x0443\x0441\x0441\x043a\x043e\x043c",
- // "전체서비스"
- L"\xc804\xccb4\xc11c\xbe44\xc2a4",
-
- // Test characters that take more than 16 bits. This will depend on whether
- // wchar_t is 16 or 32 bits.
-#if defined(WCHAR_T_IS_UTF16)
- L"\xd800\xdf00",
- // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E)
- L"\xd807\xdd40\xd807\xdd41\xd807\xdd42\xd807\xdd43\xd807\xdd44",
-#elif defined(WCHAR_T_IS_UTF32)
- L"\x10300",
- // ????? (Mathematical Alphanumeric Symbols (U+011d40 - U+011d44 : A,B,C,D,E)
- L"\x11d40\x11d41\x11d42\x11d43\x11d44",
-#endif
-};
-
-} // namespace
-
-TEST(UTFStringConversionsTest, ConvertUTF8AndWide) {
- // we round-trip all the wide strings through UTF-8 to make sure everything
- // agrees on the conversion. This uses the stream operators to test them
- // simultaneously.
- for (size_t i = 0; i < arraysize(kConvertRoundtripCases); ++i) {
- std::ostringstream utf8;
- utf8 << WideToUTF8(kConvertRoundtripCases[i]);
- std::wostringstream wide;
- wide << UTF8ToWide(utf8.str());
-
- EXPECT_EQ(kConvertRoundtripCases[i], wide.str());
- }
-}
-
-TEST(UTFStringConversionsTest, ConvertUTF8AndWideEmptyString) {
- // An empty std::wstring should be converted to an empty std::string,
- // and vice versa.
- std::wstring wempty;
- std::string empty;
- EXPECT_EQ(empty, WideToUTF8(wempty));
- EXPECT_EQ(wempty, UTF8ToWide(empty));
-}
-
-TEST(UTFStringConversionsTest, ConvertUTF8ToWide) {
- struct UTF8ToWideCase {
- const char* utf8;
- const wchar_t* wide;
- bool success;
- } convert_cases[] = {
- // Regular UTF-8 input.
- {"\xe4\xbd\xa0\xe5\xa5\xbd", L"\x4f60\x597d", true},
- // Non-character is passed through.
- {"\xef\xbf\xbfHello", L"\xffffHello", true},
- // Truncated UTF-8 sequence.
- {"\xe4\xa0\xe5\xa5\xbd", L"\xfffd\x597d", false},
- // Truncated off the end.
- {"\xe5\xa5\xbd\xe4\xa0", L"\x597d\xfffd", false},
- // Non-shortest-form UTF-8.
- {"\xf0\x84\xbd\xa0\xe5\xa5\xbd", L"\xfffd\xfffd\xfffd\xfffd\x597d", false},
- // This UTF-8 character decodes to a UTF-16 surrogate, which is illegal.
- {"\xed\xb0\x80", L"\xfffd\xfffd\xfffd", false},
- // Non-BMP characters. The second is a non-character regarded as valid.
- // The result will either be in UTF-16 or UTF-32.
-#if defined(WCHAR_T_IS_UTF16)
- {"A\xF0\x90\x8C\x80z", L"A\xd800\xdf00z", true},
- {"A\xF4\x8F\xBF\xBEz", L"A\xdbff\xdffez", true},
-#elif defined(WCHAR_T_IS_UTF32)
- {"A\xF0\x90\x8C\x80z", L"A\x10300z", true},
- {"A\xF4\x8F\xBF\xBEz", L"A\x10fffez", true},
-#endif
- };
-
- for (size_t i = 0; i < arraysize(convert_cases); i++) {
- std::wstring converted;
- EXPECT_EQ(convert_cases[i].success,
- UTF8ToWide(convert_cases[i].utf8,
- strlen(convert_cases[i].utf8),
- &converted));
- std::wstring expected(convert_cases[i].wide);
- EXPECT_EQ(expected, converted);
- }
-
- // Manually test an embedded NULL.
- std::wstring converted;
- EXPECT_TRUE(UTF8ToWide("\00Z\t", 3, &converted));
- ASSERT_EQ(3U, converted.length());
- EXPECT_EQ(static_cast<wchar_t>(0), converted[0]);
- EXPECT_EQ('Z', converted[1]);
- EXPECT_EQ('\t', converted[2]);
-
- // Make sure that conversion replaces, not appends.
- EXPECT_TRUE(UTF8ToWide("B", 1, &converted));
- ASSERT_EQ(1U, converted.length());
- EXPECT_EQ('B', converted[0]);
-}
-
-#if defined(WCHAR_T_IS_UTF16)
-// This test is only valid when wchar_t == UTF-16.
-TEST(UTFStringConversionsTest, ConvertUTF16ToUTF8) {
- struct WideToUTF8Case {
- const wchar_t* utf16;
- const char* utf8;
- bool success;
- } convert_cases[] = {
- // Regular UTF-16 input.
- {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true},
- // Test a non-BMP character.
- {L"\xd800\xdf00", "\xF0\x90\x8C\x80", true},
- // Non-characters are passed through.
- {L"\xffffHello", "\xEF\xBF\xBFHello", true},
- {L"\xdbff\xdffeHello", "\xF4\x8F\xBF\xBEHello", true},
- // The first character is a truncated UTF-16 character.
- {L"\xd800\x597d", "\xef\xbf\xbd\xe5\xa5\xbd", false},
- // Truncated at the end.
- {L"\x597d\xd800", "\xe5\xa5\xbd\xef\xbf\xbd", false},
- };
-
- for (const auto& test : convert_cases) {
- std::string converted;
- EXPECT_EQ(test.success,
- WideToUTF8(test.utf16, wcslen(test.utf16), &converted));
- std::string expected(test.utf8);
- EXPECT_EQ(expected, converted);
- }
-}
-
-#elif defined(WCHAR_T_IS_UTF32)
-// This test is only valid when wchar_t == UTF-32.
-TEST(UTFStringConversionsTest, ConvertUTF32ToUTF8) {
- struct WideToUTF8Case {
- const wchar_t* utf32;
- const char* utf8;
- bool success;
- } convert_cases[] = {
- // Regular 16-bit input.
- {L"\x4f60\x597d", "\xe4\xbd\xa0\xe5\xa5\xbd", true},
- // Test a non-BMP character.
- {L"A\x10300z", "A\xF0\x90\x8C\x80z", true},
- // Non-characters are passed through.
- {L"\xffffHello", "\xEF\xBF\xBFHello", true},
- {L"\x10fffeHello", "\xF4\x8F\xBF\xBEHello", true},
- // Invalid Unicode code points.
- {L"\xfffffffHello", "\xEF\xBF\xBDHello", false},
- // The first character is a truncated UTF-16 character.
- {L"\xd800\x597d", "\xef\xbf\xbd\xe5\xa5\xbd", false},
- {L"\xdc01Hello", "\xef\xbf\xbdHello", false},
- };
-
- for (const auto& test : convert_cases) {
- std::string converted;
- EXPECT_EQ(test.success,
- WideToUTF8(test.utf32, wcslen(test.utf32), &converted));
- std::string expected(test.utf8);
- EXPECT_EQ(expected, converted);
- }
-}
-#endif // defined(WCHAR_T_IS_UTF32)
-
-TEST(UTFStringConversionsTest, ConvertMultiString) {
- static char16 multi16[] = {
- 'f', 'o', 'o', '\0',
- 'b', 'a', 'r', '\0',
- 'b', 'a', 'z', '\0',
- '\0'
- };
- static char multi[] = {
- 'f', 'o', 'o', '\0',
- 'b', 'a', 'r', '\0',
- 'b', 'a', 'z', '\0',
- '\0'
- };
- string16 multistring16;
- memcpy(WriteInto(&multistring16, arraysize(multi16)), multi16,
- sizeof(multi16));
- EXPECT_EQ(arraysize(multi16) - 1, multistring16.length());
- std::string expected;
- memcpy(WriteInto(&expected, arraysize(multi)), multi, sizeof(multi));
- EXPECT_EQ(arraysize(multi) - 1, expected.length());
- const std::string& converted = UTF16ToUTF8(multistring16);
- EXPECT_EQ(arraysize(multi) - 1, converted.length());
- EXPECT_EQ(expected, converted);
-}
-
-} // namespace base
diff --git a/base/supports_user_data_unittest.cc b/base/supports_user_data_unittest.cc
deleted file mode 100644
index 2e0a724..0000000
--- 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/sync_socket_unittest.cc b/base/sync_socket_unittest.cc
deleted file mode 100644
index fdcd9a1..0000000
--- a/base/sync_socket_unittest.cc
+++ /dev/null
@@ -1,190 +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/sync_socket.h"
-
-#include "base/macros.h"
-#include "base/synchronization/waitable_event.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 {
-
-constexpr TimeDelta kReceiveTimeout = base::TimeDelta::FromMilliseconds(750);
-
-class HangingReceiveThread : public DelegateSimpleThread::Delegate {
- public:
- explicit HangingReceiveThread(SyncSocket* socket, bool with_timeout)
- : socket_(socket),
- thread_(this, "HangingReceiveThread"),
- with_timeout_(with_timeout),
- started_event_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- done_event_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {
- thread_.Start();
- }
-
- ~HangingReceiveThread() override = default;
-
- void Run() override {
- int data = 0;
- ASSERT_EQ(socket_->Peek(), 0u);
-
- started_event_.Signal();
-
- if (with_timeout_) {
- ASSERT_EQ(0u, socket_->ReceiveWithTimeout(&data, sizeof(data),
- kReceiveTimeout));
- } else {
- ASSERT_EQ(0u, socket_->Receive(&data, sizeof(data)));
- }
-
- done_event_.Signal();
- }
-
- void Stop() {
- thread_.Join();
- }
-
- WaitableEvent* started_event() { return &started_event_; }
- WaitableEvent* done_event() { return &done_event_; }
-
- private:
- SyncSocket* socket_;
- DelegateSimpleThread thread_;
- bool with_timeout_;
- WaitableEvent started_event_;
- WaitableEvent done_event_;
-
- DISALLOW_COPY_AND_ASSIGN(HangingReceiveThread);
-};
-
-// Tests sending data between two SyncSockets. Uses ASSERT() and thus will exit
-// early upon failure. Callers should use ASSERT_NO_FATAL_FAILURE() if testing
-// continues after return.
-void SendReceivePeek(SyncSocket* socket_a, SyncSocket* socket_b) {
- int received = 0;
- const int kSending = 123;
- static_assert(sizeof(kSending) == sizeof(received), "invalid data size");
-
- ASSERT_EQ(0u, socket_a->Peek());
- ASSERT_EQ(0u, socket_b->Peek());
-
- // Verify |socket_a| can send to |socket_a| and |socket_a| can Receive from
- // |socket_a|.
- ASSERT_EQ(sizeof(kSending), socket_a->Send(&kSending, sizeof(kSending)));
- ASSERT_EQ(sizeof(kSending), socket_b->Peek());
- ASSERT_EQ(sizeof(kSending), socket_b->Receive(&received, sizeof(kSending)));
- ASSERT_EQ(kSending, received);
-
- ASSERT_EQ(0u, socket_a->Peek());
- ASSERT_EQ(0u, socket_b->Peek());
-
- // Now verify the reverse.
- received = 0;
- ASSERT_EQ(sizeof(kSending), socket_b->Send(&kSending, sizeof(kSending)));
- ASSERT_EQ(sizeof(kSending), socket_a->Peek());
- ASSERT_EQ(sizeof(kSending), socket_a->Receive(&received, sizeof(kSending)));
- ASSERT_EQ(kSending, received);
-
- ASSERT_EQ(0u, socket_a->Peek());
- ASSERT_EQ(0u, socket_b->Peek());
-
- ASSERT_TRUE(socket_a->Close());
- ASSERT_TRUE(socket_b->Close());
-}
-
-} // namespace
-
-class SyncSocketTest : public testing::Test {
- public:
- void SetUp() override {
- ASSERT_TRUE(SyncSocket::CreatePair(&socket_a_, &socket_b_));
- }
-
- protected:
- SyncSocket socket_a_;
- SyncSocket socket_b_;
-};
-
-TEST_F(SyncSocketTest, NormalSendReceivePeek) {
- SendReceivePeek(&socket_a_, &socket_b_);
-}
-
-TEST_F(SyncSocketTest, ClonedSendReceivePeek) {
- SyncSocket socket_c(socket_a_.Release());
- SyncSocket socket_d(socket_b_.Release());
- SendReceivePeek(&socket_c, &socket_d);
-};
-
-class CancelableSyncSocketTest : public testing::Test {
- public:
- void SetUp() override {
- ASSERT_TRUE(CancelableSyncSocket::CreatePair(&socket_a_, &socket_b_));
- }
-
- protected:
- CancelableSyncSocket socket_a_;
- CancelableSyncSocket socket_b_;
-};
-
-TEST_F(CancelableSyncSocketTest, NormalSendReceivePeek) {
- SendReceivePeek(&socket_a_, &socket_b_);
-}
-
-TEST_F(CancelableSyncSocketTest, ClonedSendReceivePeek) {
- CancelableSyncSocket socket_c(socket_a_.Release());
- CancelableSyncSocket socket_d(socket_b_.Release());
- SendReceivePeek(&socket_c, &socket_d);
-}
-
-TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceive) {
- HangingReceiveThread thread(&socket_b_, /* with_timeout = */ false);
-
- // Wait for the thread to be started. Note that this doesn't guarantee that
- // Receive() is called before Shutdown().
- thread.started_event()->Wait();
-
- EXPECT_TRUE(socket_b_.Shutdown());
- EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
-
- thread.Stop();
-}
-
-TEST_F(CancelableSyncSocketTest, ShutdownCancelsReceiveWithTimeout) {
- HangingReceiveThread thread(&socket_b_, /* with_timeout = */ true);
-
- // Wait for the thread to be started. Note that this doesn't guarantee that
- // Receive() is called before Shutdown().
- thread.started_event()->Wait();
-
- EXPECT_TRUE(socket_b_.Shutdown());
- EXPECT_TRUE(thread.done_event()->TimedWait(kReceiveTimeout));
-
- thread.Stop();
-}
-
-TEST_F(CancelableSyncSocketTest, ReceiveAfterShutdown) {
- socket_a_.Shutdown();
- int data = 0;
- EXPECT_EQ(0u, socket_a_.Receive(&data, sizeof(data)));
-}
-
-TEST_F(CancelableSyncSocketTest, ReceiveWithTimeoutAfterShutdown) {
- socket_a_.Shutdown();
- TimeTicks start = TimeTicks::Now();
- int data = 0;
- EXPECT_EQ(0u,
- socket_a_.ReceiveWithTimeout(&data, sizeof(data), kReceiveTimeout));
-
- // Ensure the receive didn't just timeout.
- EXPECT_LT(TimeTicks::Now() - start, kReceiveTimeout);
-}
-
-} // namespace base
diff --git a/base/synchronization/atomic_flag_unittest.cc b/base/synchronization/atomic_flag_unittest.cc
deleted file mode 100644
index 1a3da7f..0000000
--- a/base/synchronization/atomic_flag_unittest.cc
+++ /dev/null
@@ -1,135 +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/synchronization/atomic_flag.h"
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-void ExpectSetFlagDeath(AtomicFlag* flag) {
- ASSERT_TRUE(flag);
- EXPECT_DCHECK_DEATH(flag->Set());
-}
-
-// Busy waits (to explicitly avoid using synchronization constructs that would
-// defeat the purpose of testing atomics) until |tested_flag| is set and then
-// verifies that non-atomic |*expected_after_flag| is true and sets |*done_flag|
-// before returning if it's non-null.
-void BusyWaitUntilFlagIsSet(AtomicFlag* tested_flag, bool* expected_after_flag,
- AtomicFlag* done_flag) {
- while (!tested_flag->IsSet())
- PlatformThread::YieldCurrentThread();
-
- EXPECT_TRUE(*expected_after_flag);
- if (done_flag)
- done_flag->Set();
-}
-
-} // namespace
-
-TEST(AtomicFlagTest, SimpleSingleThreadedTest) {
- AtomicFlag flag;
- ASSERT_FALSE(flag.IsSet());
- flag.Set();
- ASSERT_TRUE(flag.IsSet());
-}
-
-TEST(AtomicFlagTest, DoubleSetTest) {
- AtomicFlag flag;
- ASSERT_FALSE(flag.IsSet());
- flag.Set();
- ASSERT_TRUE(flag.IsSet());
- flag.Set();
- ASSERT_TRUE(flag.IsSet());
-}
-
-TEST(AtomicFlagTest, ReadFromDifferentThread) {
- // |tested_flag| is the one being tested below.
- AtomicFlag tested_flag;
- // |expected_after_flag| is used to confirm that sequential consistency is
- // obtained around |tested_flag|.
- bool expected_after_flag = false;
- // |reset_flag| is used to confirm the test flows as intended without using
- // synchronization constructs which would defeat the purpose of exercising
- // atomics.
- AtomicFlag reset_flag;
-
- Thread thread("AtomicFlagTest.ReadFromDifferentThread");
- ASSERT_TRUE(thread.Start());
- thread.task_runner()->PostTask(FROM_HERE,
- BindOnce(&BusyWaitUntilFlagIsSet, &tested_flag,
- &expected_after_flag, &reset_flag));
-
- // To verify that IsSet() fetches the flag's value from memory every time it
- // is called (not just the first time that it is called on a thread), sleep
- // before setting the flag.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));
-
- // |expected_after_flag| is used to verify that all memory operations
- // performed before |tested_flag| is Set() are visible to threads that can see
- // IsSet().
- expected_after_flag = true;
- tested_flag.Set();
-
- // Sleep again to give the busy loop time to observe the flag and verify
- // expectations.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));
-
- // Use |reset_flag| to confirm that the above completed (which the rest of
- // this test assumes).
- while (!reset_flag.IsSet())
- PlatformThread::YieldCurrentThread();
-
- tested_flag.UnsafeResetForTesting();
- EXPECT_FALSE(tested_flag.IsSet());
- expected_after_flag = false;
-
- // Perform the same test again after the controlled UnsafeResetForTesting(),
- // |thread| is guaranteed to be synchronized past the
- // |UnsafeResetForTesting()| call when the task runs per the implicit
- // synchronization in the post task mechanism.
- thread.task_runner()->PostTask(FROM_HERE,
- BindOnce(&BusyWaitUntilFlagIsSet, &tested_flag,
- &expected_after_flag, nullptr));
-
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));
-
- expected_after_flag = true;
- tested_flag.Set();
-
- // The |thread|'s destructor will block until the posted task completes, so
- // the test will time out if it fails to see the flag be set.
-}
-
-TEST(AtomicFlagTest, SetOnDifferentSequenceDeathTest) {
- // Checks that Set() can't be called from another sequence after being called
- // on this one. AtomicFlag should die on a DCHECK if Set() is called again
- // from another sequence.
-
- // Note: flag must be declared before the Thread so that its destructor runs
- // later. Otherwise there's a race between destructing flag and running
- // ExpectSetFlagDeath.
- AtomicFlag flag;
-
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- Thread t("AtomicFlagTest.SetOnDifferentThreadDeathTest");
- ASSERT_TRUE(t.Start());
- EXPECT_TRUE(t.WaitUntilThreadStarted());
-
- flag.Set();
- t.task_runner()->PostTask(FROM_HERE, BindOnce(&ExpectSetFlagDeath, &flag));
-}
-
-} // namespace base
diff --git a/base/synchronization/condition_variable_unittest.cc b/base/synchronization/condition_variable_unittest.cc
deleted file mode 100644
index 929060a..0000000
--- a/base/synchronization/condition_variable_unittest.cc
+++ /dev/null
@@ -1,768 +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.
-
-// Multi-threaded tests of ConditionVariable class.
-
-#include "base/synchronization/condition_variable.h"
-
-#include <time.h>
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/lock.h"
-#include "base/synchronization/spin_wait.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_collision_warner.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace base {
-
-namespace {
-//------------------------------------------------------------------------------
-// Define our test class, with several common variables.
-//------------------------------------------------------------------------------
-
-class ConditionVariableTest : public PlatformTest {
- public:
- const TimeDelta kZeroMs;
- const TimeDelta kTenMs;
- const TimeDelta kThirtyMs;
- const TimeDelta kFortyFiveMs;
- const TimeDelta kSixtyMs;
- const TimeDelta kOneHundredMs;
-
- ConditionVariableTest()
- : kZeroMs(TimeDelta::FromMilliseconds(0)),
- kTenMs(TimeDelta::FromMilliseconds(10)),
- kThirtyMs(TimeDelta::FromMilliseconds(30)),
- kFortyFiveMs(TimeDelta::FromMilliseconds(45)),
- kSixtyMs(TimeDelta::FromMilliseconds(60)),
- kOneHundredMs(TimeDelta::FromMilliseconds(100)) {
- }
-};
-
-//------------------------------------------------------------------------------
-// Define a class that will control activities an several multi-threaded tests.
-// The general structure of multi-threaded tests is that a test case will
-// construct an instance of a WorkQueue. The WorkQueue will spin up some
-// threads and control them throughout their lifetime, as well as maintaining
-// a central repository of the work thread's activity. Finally, the WorkQueue
-// will command the the worker threads to terminate. At that point, the test
-// cases will validate that the WorkQueue has records showing that the desired
-// activities were performed.
-//------------------------------------------------------------------------------
-
-// Callers are responsible for synchronizing access to the following class.
-// The WorkQueue::lock_, as accessed via WorkQueue::lock(), should be used for
-// all synchronized access.
-class WorkQueue : public PlatformThread::Delegate {
- public:
- explicit WorkQueue(int thread_count);
- ~WorkQueue() override;
-
- // PlatformThread::Delegate interface.
- void ThreadMain() override;
-
- //----------------------------------------------------------------------------
- // Worker threads only call the following methods.
- // They should use the lock to get exclusive access.
- int GetThreadId(); // Get an ID assigned to a thread..
- bool EveryIdWasAllocated() const; // Indicates that all IDs were handed out.
- TimeDelta GetAnAssignment(int thread_id); // Get a work task duration.
- void WorkIsCompleted(int thread_id);
-
- int task_count() const;
- bool allow_help_requests() const; // Workers can signal more workers.
- bool shutdown() const; // Check if shutdown has been requested.
-
- void thread_shutting_down();
-
-
- //----------------------------------------------------------------------------
- // Worker threads can call them but not needed to acquire a lock.
- Lock* lock();
-
- ConditionVariable* work_is_available();
- ConditionVariable* all_threads_have_ids();
- ConditionVariable* no_more_tasks();
-
- //----------------------------------------------------------------------------
- // The rest of the methods are for use by the controlling master thread (the
- // test case code).
- void ResetHistory();
- int GetMinCompletionsByWorkerThread() const;
- int GetMaxCompletionsByWorkerThread() const;
- int GetNumThreadsTakingAssignments() const;
- int GetNumThreadsCompletingTasks() const;
- int GetNumberOfCompletedTasks() const;
-
- void SetWorkTime(TimeDelta delay);
- void SetTaskCount(int count);
- void SetAllowHelp(bool allow);
-
- // The following must be called without locking, and will spin wait until the
- // threads are all in a wait state.
- void SpinUntilAllThreadsAreWaiting();
- void SpinUntilTaskCountLessThan(int task_count);
-
- // Caller must acquire lock before calling.
- void SetShutdown();
-
- // Compares the |shutdown_task_count_| to the |thread_count| and returns true
- // if they are equal. This check will acquire the |lock_| so the caller
- // should not hold the lock when calling this method.
- bool ThreadSafeCheckShutdown(int thread_count);
-
- private:
- // Both worker threads and controller use the following to synchronize.
- Lock lock_;
- ConditionVariable work_is_available_; // To tell threads there is work.
-
- // Conditions to notify the controlling process (if it is interested).
- ConditionVariable all_threads_have_ids_; // All threads are running.
- ConditionVariable no_more_tasks_; // Task count is zero.
-
- const int thread_count_;
- int waiting_thread_count_;
- std::unique_ptr<PlatformThreadHandle[]> thread_handles_;
- std::vector<int> assignment_history_; // Number of assignment per worker.
- std::vector<int> completion_history_; // Number of completions per worker.
- int thread_started_counter_; // Used to issue unique id to workers.
- int shutdown_task_count_; // Number of tasks told to shutdown
- int task_count_; // Number of assignment tasks waiting to be processed.
- TimeDelta worker_delay_; // Time each task takes to complete.
- bool allow_help_requests_; // Workers can signal more workers.
- bool shutdown_; // Set when threads need to terminate.
-
- DFAKE_MUTEX(locked_methods_);
-};
-
-//------------------------------------------------------------------------------
-// The next section contains the actual tests.
-//------------------------------------------------------------------------------
-
-TEST_F(ConditionVariableTest, StartupShutdownTest) {
- Lock lock;
-
- // First try trivial startup/shutdown.
- {
- ConditionVariable cv1(&lock);
- } // Call for cv1 destruction.
-
- // Exercise with at least a few waits.
- ConditionVariable cv(&lock);
-
- lock.Acquire();
- cv.TimedWait(kTenMs); // Wait for 10 ms.
- cv.TimedWait(kTenMs); // Wait for 10 ms.
- lock.Release();
-
- lock.Acquire();
- cv.TimedWait(kTenMs); // Wait for 10 ms.
- cv.TimedWait(kTenMs); // Wait for 10 ms.
- cv.TimedWait(kTenMs); // Wait for 10 ms.
- lock.Release();
-} // Call for cv destruction.
-
-TEST_F(ConditionVariableTest, TimeoutTest) {
- Lock lock;
- ConditionVariable cv(&lock);
- lock.Acquire();
-
- TimeTicks start = TimeTicks::Now();
- const TimeDelta WAIT_TIME = TimeDelta::FromMilliseconds(300);
- // Allow for clocking rate granularity.
- const TimeDelta FUDGE_TIME = TimeDelta::FromMilliseconds(50);
-
- cv.TimedWait(WAIT_TIME + FUDGE_TIME);
- TimeDelta duration = TimeTicks::Now() - start;
- // We can't use EXPECT_GE here as the TimeDelta class does not support the
- // required stream conversion.
- EXPECT_TRUE(duration >= WAIT_TIME);
-
- lock.Release();
-}
-
-#if defined(OS_POSIX) && !defined(OS_FUCHSIA)
-const int kDiscontinuitySeconds = 2;
-
-void BackInTime(Lock* lock) {
- AutoLock auto_lock(*lock);
-
- timeval tv;
- gettimeofday(&tv, nullptr);
- tv.tv_sec -= kDiscontinuitySeconds;
- settimeofday(&tv, nullptr);
-}
-
-// Tests that TimedWait ignores changes to the system clock.
-// Test is disabled by default, because it needs to run as root to muck with the
-// system clock.
-// http://crbug.com/293736
-TEST_F(ConditionVariableTest, DISABLED_TimeoutAcrossSetTimeOfDay) {
- timeval tv;
- gettimeofday(&tv, nullptr);
- tv.tv_sec += kDiscontinuitySeconds;
- if (settimeofday(&tv, nullptr) < 0) {
- PLOG(ERROR) << "Could not set time of day. Run as root?";
- return;
- }
-
- Lock lock;
- ConditionVariable cv(&lock);
- lock.Acquire();
-
- Thread thread("Helper");
- thread.Start();
- thread.task_runner()->PostTask(FROM_HERE, base::BindOnce(&BackInTime, &lock));
-
- TimeTicks start = TimeTicks::Now();
- const TimeDelta kWaitTime = TimeDelta::FromMilliseconds(300);
- // Allow for clocking rate granularity.
- const TimeDelta kFudgeTime = TimeDelta::FromMilliseconds(50);
-
- cv.TimedWait(kWaitTime + kFudgeTime);
- TimeDelta duration = TimeTicks::Now() - start;
-
- thread.Stop();
- // We can't use EXPECT_GE here as the TimeDelta class does not support the
- // required stream conversion.
- EXPECT_TRUE(duration >= kWaitTime);
- EXPECT_TRUE(duration <= TimeDelta::FromSeconds(kDiscontinuitySeconds));
-
- lock.Release();
-}
-#endif
-
-
-// Suddenly got flaky on Win, see http://crbug.com/10607 (starting at
-// comment #15).
-#if defined(OS_WIN)
-#define MAYBE_MultiThreadConsumerTest DISABLED_MultiThreadConsumerTest
-#else
-#define MAYBE_MultiThreadConsumerTest MultiThreadConsumerTest
-#endif
-// Test serial task servicing, as well as two parallel task servicing methods.
-TEST_F(ConditionVariableTest, MAYBE_MultiThreadConsumerTest) {
- const int kThreadCount = 10;
- WorkQueue queue(kThreadCount); // Start the threads.
-
- const int kTaskCount = 10; // Number of tasks in each mini-test here.
-
- Time start_time; // Used to time task processing.
-
- {
- base::AutoLock auto_lock(*queue.lock());
- while (!queue.EveryIdWasAllocated())
- queue.all_threads_have_ids()->Wait();
- }
-
- // If threads aren't in a wait state, they may start to gobble up tasks in
- // parallel, short-circuiting (breaking) this test.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- // Since we have no tasks yet, all threads should be waiting by now.
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
- EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
- EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
-
- // Set up to make each task include getting help from another worker, so
- // so that the work gets done in paralell.
- queue.ResetHistory();
- queue.SetTaskCount(kTaskCount);
- queue.SetWorkTime(kThirtyMs);
- queue.SetAllowHelp(true);
-
- start_time = Time::Now();
- }
-
- queue.work_is_available()->Signal(); // But each worker can signal another.
- // Wait till we at least start to handle tasks (and we're not all waiting).
- queue.SpinUntilTaskCountLessThan(kTaskCount);
- // Wait to allow the all workers to get done.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- // Wait until all work tasks have at least been assigned.
- base::AutoLock auto_lock(*queue.lock());
- while (queue.task_count())
- queue.no_more_tasks()->Wait();
-
- // To avoid racy assumptions, we'll just assert that at least 2 threads
- // did work. We know that the first worker should have gone to sleep, and
- // hence a second worker should have gotten an assignment.
- EXPECT_LE(2, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(kTaskCount, queue.GetNumberOfCompletedTasks());
-
- // Try to ask all workers to help, and only a few will do the work.
- queue.ResetHistory();
- queue.SetTaskCount(3);
- queue.SetWorkTime(kThirtyMs);
- queue.SetAllowHelp(false);
- }
- queue.work_is_available()->Broadcast(); // Make them all try.
- // Wait till we at least start to handle tasks (and we're not all waiting).
- queue.SpinUntilTaskCountLessThan(3);
- // Wait to allow the 3 workers to get done.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
- EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
- EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
-
- // Set up to make each task get help from another worker.
- queue.ResetHistory();
- queue.SetTaskCount(3);
- queue.SetWorkTime(kThirtyMs);
- queue.SetAllowHelp(true); // Allow (unnecessary) help requests.
- }
- queue.work_is_available()->Broadcast(); // Signal all threads.
- // Wait till we at least start to handle tasks (and we're not all waiting).
- queue.SpinUntilTaskCountLessThan(3);
- // Wait to allow the 3 workers to get done.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(3, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(3, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_EQ(1, queue.GetMaxCompletionsByWorkerThread());
- EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
- EXPECT_EQ(3, queue.GetNumberOfCompletedTasks());
-
- // Set up to make each task get help from another worker.
- queue.ResetHistory();
- queue.SetTaskCount(20); // 2 tasks per thread.
- queue.SetWorkTime(kThirtyMs);
- queue.SetAllowHelp(true);
- }
- queue.work_is_available()->Signal(); // But each worker can signal another.
- // Wait till we at least start to handle tasks (and we're not all waiting).
- queue.SpinUntilTaskCountLessThan(20);
- // Wait to allow the 10 workers to get done.
- queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
-
- {
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
-
- // Same as last test, but with Broadcast().
- queue.ResetHistory();
- queue.SetTaskCount(20); // 2 tasks per thread.
- queue.SetWorkTime(kThirtyMs);
- queue.SetAllowHelp(true);
- }
- queue.work_is_available()->Broadcast();
- // Wait till we at least start to handle tasks (and we're not all waiting).
- queue.SpinUntilTaskCountLessThan(20);
- // Wait to allow the 10 workers to get done.
- queue.SpinUntilAllThreadsAreWaiting(); // Should take about 60 ms.
-
- {
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(10, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(10, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_EQ(20, queue.GetNumberOfCompletedTasks());
-
- queue.SetShutdown();
- }
- queue.work_is_available()->Broadcast(); // Force check for shutdown.
-
- SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
- queue.ThreadSafeCheckShutdown(kThreadCount));
-}
-
-TEST_F(ConditionVariableTest, LargeFastTaskTest) {
- const int kThreadCount = 200;
- WorkQueue queue(kThreadCount); // Start the threads.
-
- Lock private_lock; // Used locally for master to wait.
- base::AutoLock private_held_lock(private_lock);
- ConditionVariable private_cv(&private_lock);
-
- {
- base::AutoLock auto_lock(*queue.lock());
- while (!queue.EveryIdWasAllocated())
- queue.all_threads_have_ids()->Wait();
- }
-
- // Wait a bit more to allow threads to reach their wait state.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- // Since we have no tasks, all threads should be waiting by now.
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(0, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(0, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_EQ(0, queue.GetMaxCompletionsByWorkerThread());
- EXPECT_EQ(0, queue.GetMinCompletionsByWorkerThread());
- EXPECT_EQ(0, queue.GetNumberOfCompletedTasks());
-
- // Set up to make all workers do (an average of) 20 tasks.
- queue.ResetHistory();
- queue.SetTaskCount(20 * kThreadCount);
- queue.SetWorkTime(kFortyFiveMs);
- queue.SetAllowHelp(false);
- }
- queue.work_is_available()->Broadcast(); // Start up all threads.
- // Wait until we've handed out all tasks.
- {
- base::AutoLock auto_lock(*queue.lock());
- while (queue.task_count() != 0)
- queue.no_more_tasks()->Wait();
- }
-
- // Wait till the last of the tasks complete.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- // With Broadcast(), every thread should have participated.
- // but with racing.. they may not all have done equal numbers of tasks.
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_LE(20, queue.GetMaxCompletionsByWorkerThread());
- EXPECT_EQ(20 * kThreadCount, queue.GetNumberOfCompletedTasks());
-
- // Set up to make all workers do (an average of) 4 tasks.
- queue.ResetHistory();
- queue.SetTaskCount(kThreadCount * 4);
- queue.SetWorkTime(kFortyFiveMs);
- queue.SetAllowHelp(true); // Might outperform Broadcast().
- }
- queue.work_is_available()->Signal(); // Start up one thread.
-
- // Wait until we've handed out all tasks
- {
- base::AutoLock auto_lock(*queue.lock());
- while (queue.task_count() != 0)
- queue.no_more_tasks()->Wait();
- }
-
- // Wait till the last of the tasks complete.
- queue.SpinUntilAllThreadsAreWaiting();
-
- {
- // With Signal(), every thread should have participated.
- // but with racing.. they may not all have done four tasks.
- base::AutoLock auto_lock(*queue.lock());
- EXPECT_EQ(kThreadCount, queue.GetNumThreadsTakingAssignments());
- EXPECT_EQ(kThreadCount, queue.GetNumThreadsCompletingTasks());
- EXPECT_EQ(0, queue.task_count());
- EXPECT_LE(4, queue.GetMaxCompletionsByWorkerThread());
- EXPECT_EQ(4 * kThreadCount, queue.GetNumberOfCompletedTasks());
-
- queue.SetShutdown();
- }
- queue.work_is_available()->Broadcast(); // Force check for shutdown.
-
- // Wait for shutdowns to complete.
- SPIN_FOR_TIMEDELTA_OR_UNTIL_TRUE(TimeDelta::FromMinutes(1),
- queue.ThreadSafeCheckShutdown(kThreadCount));
-}
-
-//------------------------------------------------------------------------------
-// Finally we provide the implementation for the methods in the WorkQueue class.
-//------------------------------------------------------------------------------
-
-WorkQueue::WorkQueue(int thread_count)
- : lock_(),
- work_is_available_(&lock_),
- all_threads_have_ids_(&lock_),
- no_more_tasks_(&lock_),
- thread_count_(thread_count),
- waiting_thread_count_(0),
- thread_handles_(new PlatformThreadHandle[thread_count]),
- assignment_history_(thread_count),
- completion_history_(thread_count),
- thread_started_counter_(0),
- shutdown_task_count_(0),
- task_count_(0),
- allow_help_requests_(false),
- shutdown_(false) {
- EXPECT_GE(thread_count_, 1);
- ResetHistory();
- SetTaskCount(0);
- SetWorkTime(TimeDelta::FromMilliseconds(30));
-
- for (int i = 0; i < thread_count_; ++i) {
- PlatformThreadHandle pth;
- EXPECT_TRUE(PlatformThread::Create(0, this, &pth));
- thread_handles_[i] = pth;
- }
-}
-
-WorkQueue::~WorkQueue() {
- {
- base::AutoLock auto_lock(lock_);
- SetShutdown();
- }
- work_is_available_.Broadcast(); // Tell them all to terminate.
-
- for (int i = 0; i < thread_count_; ++i) {
- PlatformThread::Join(thread_handles_[i]);
- }
- EXPECT_EQ(0, waiting_thread_count_);
-}
-
-int WorkQueue::GetThreadId() {
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- DCHECK(!EveryIdWasAllocated());
- return thread_started_counter_++; // Give out Unique IDs.
-}
-
-bool WorkQueue::EveryIdWasAllocated() const {
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- return thread_count_ == thread_started_counter_;
-}
-
-TimeDelta WorkQueue::GetAnAssignment(int thread_id) {
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- DCHECK_LT(0, task_count_);
- assignment_history_[thread_id]++;
- if (0 == --task_count_) {
- no_more_tasks_.Signal();
- }
- return worker_delay_;
-}
-
-void WorkQueue::WorkIsCompleted(int thread_id) {
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- completion_history_[thread_id]++;
-}
-
-int WorkQueue::task_count() const {
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- return task_count_;
-}
-
-bool WorkQueue::allow_help_requests() const {
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- return allow_help_requests_;
-}
-
-bool WorkQueue::shutdown() const {
- lock_.AssertAcquired();
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- return shutdown_;
-}
-
-// Because this method is called from the test's main thread we need to actually
-// take the lock. Threads will call the thread_shutting_down() method with the
-// lock already acquired.
-bool WorkQueue::ThreadSafeCheckShutdown(int thread_count) {
- bool all_shutdown;
- base::AutoLock auto_lock(lock_);
- {
- // Declare in scope so DFAKE is guranteed to be destroyed before AutoLock.
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- all_shutdown = (shutdown_task_count_ == thread_count);
- }
- return all_shutdown;
-}
-
-void WorkQueue::thread_shutting_down() {
- lock_.AssertAcquired();
- DFAKE_SCOPED_RECURSIVE_LOCK(locked_methods_);
- shutdown_task_count_++;
-}
-
-Lock* WorkQueue::lock() {
- return &lock_;
-}
-
-ConditionVariable* WorkQueue::work_is_available() {
- return &work_is_available_;
-}
-
-ConditionVariable* WorkQueue::all_threads_have_ids() {
- return &all_threads_have_ids_;
-}
-
-ConditionVariable* WorkQueue::no_more_tasks() {
- return &no_more_tasks_;
-}
-
-void WorkQueue::ResetHistory() {
- for (int i = 0; i < thread_count_; ++i) {
- assignment_history_[i] = 0;
- completion_history_[i] = 0;
- }
-}
-
-int WorkQueue::GetMinCompletionsByWorkerThread() const {
- int minumum = completion_history_[0];
- for (int i = 0; i < thread_count_; ++i)
- minumum = std::min(minumum, completion_history_[i]);
- return minumum;
-}
-
-int WorkQueue::GetMaxCompletionsByWorkerThread() const {
- int maximum = completion_history_[0];
- for (int i = 0; i < thread_count_; ++i)
- maximum = std::max(maximum, completion_history_[i]);
- return maximum;
-}
-
-int WorkQueue::GetNumThreadsTakingAssignments() const {
- int count = 0;
- for (int i = 0; i < thread_count_; ++i)
- if (assignment_history_[i])
- count++;
- return count;
-}
-
-int WorkQueue::GetNumThreadsCompletingTasks() const {
- int count = 0;
- for (int i = 0; i < thread_count_; ++i)
- if (completion_history_[i])
- count++;
- return count;
-}
-
-int WorkQueue::GetNumberOfCompletedTasks() const {
- int total = 0;
- for (int i = 0; i < thread_count_; ++i)
- total += completion_history_[i];
- return total;
-}
-
-void WorkQueue::SetWorkTime(TimeDelta delay) {
- worker_delay_ = delay;
-}
-
-void WorkQueue::SetTaskCount(int count) {
- task_count_ = count;
-}
-
-void WorkQueue::SetAllowHelp(bool allow) {
- allow_help_requests_ = allow;
-}
-
-void WorkQueue::SetShutdown() {
- lock_.AssertAcquired();
- shutdown_ = true;
-}
-
-void WorkQueue::SpinUntilAllThreadsAreWaiting() {
- while (true) {
- {
- base::AutoLock auto_lock(lock_);
- if (waiting_thread_count_ == thread_count_)
- break;
- }
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
- }
-}
-
-void WorkQueue::SpinUntilTaskCountLessThan(int task_count) {
- while (true) {
- {
- base::AutoLock auto_lock(lock_);
- if (task_count_ < task_count)
- break;
- }
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(30));
- }
-}
-
-
-//------------------------------------------------------------------------------
-// Define the standard worker task. Several tests will spin out many of these
-// threads.
-//------------------------------------------------------------------------------
-
-// The multithread tests involve several threads with a task to perform as
-// directed by an instance of the class WorkQueue.
-// The task is to:
-// a) Check to see if there are more tasks (there is a task counter).
-// a1) Wait on condition variable if there are no tasks currently.
-// b) Call a function to see what should be done.
-// c) Do some computation based on the number of milliseconds returned in (b).
-// d) go back to (a).
-
-// WorkQueue::ThreadMain() implements the above task for all threads.
-// It calls the controlling object to tell the creator about progress, and to
-// ask about tasks.
-
-void WorkQueue::ThreadMain() {
- int thread_id;
- {
- base::AutoLock auto_lock(lock_);
- thread_id = GetThreadId();
- if (EveryIdWasAllocated())
- all_threads_have_ids()->Signal(); // Tell creator we're ready.
- }
-
- Lock private_lock; // Used to waste time on "our work".
- while (1) { // This is the main consumer loop.
- TimeDelta work_time;
- bool could_use_help;
- {
- base::AutoLock auto_lock(lock_);
- while (0 == task_count() && !shutdown()) {
- ++waiting_thread_count_;
- work_is_available()->Wait();
- --waiting_thread_count_;
- }
- if (shutdown()) {
- // Ack the notification of a shutdown message back to the controller.
- thread_shutting_down();
- return; // Terminate.
- }
- // Get our task duration from the queue.
- work_time = GetAnAssignment(thread_id);
- could_use_help = (task_count() > 0) && allow_help_requests();
- } // Release lock
-
- // Do work (outside of locked region.
- if (could_use_help)
- work_is_available()->Signal(); // Get help from other threads.
-
- if (work_time > TimeDelta::FromMilliseconds(0)) {
- // We could just sleep(), but we'll instead further exercise the
- // condition variable class, and do a timed wait.
- base::AutoLock auto_lock(private_lock);
- ConditionVariable private_cv(&private_lock);
- private_cv.TimedWait(work_time); // Unsynchronized waiting.
- }
-
- {
- base::AutoLock auto_lock(lock_);
- // Send notification that we completed our "work."
- WorkIsCompleted(thread_id);
- }
- }
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/synchronization/lock_unittest.cc b/base/synchronization/lock_unittest.cc
deleted file mode 100644
index 1e2f998..0000000
--- a/base/synchronization/lock_unittest.cc
+++ /dev/null
@@ -1,257 +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/lock.h"
-
-#include <stdlib.h>
-
-#include "base/compiler_specific.h"
-#include "base/debug/activity_tracker.h"
-#include "base/macros.h"
-#include "base/threading/platform_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// Basic test to make sure that Acquire()/Release()/Try() don't crash ----------
-
-class BasicLockTestThread : public PlatformThread::Delegate {
- public:
- explicit BasicLockTestThread(Lock* lock) : lock_(lock), acquired_(0) {}
-
- void ThreadMain() override {
- for (int i = 0; i < 10; i++) {
- lock_->Acquire();
- acquired_++;
- lock_->Release();
- }
- for (int i = 0; i < 10; i++) {
- lock_->Acquire();
- acquired_++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
- lock_->Release();
- }
- for (int i = 0; i < 10; i++) {
- if (lock_->Try()) {
- acquired_++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
- lock_->Release();
- }
- }
- }
-
- int acquired() const { return acquired_; }
-
- private:
- Lock* lock_;
- int acquired_;
-
- DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
-};
-
-TEST(LockTest, Basic) {
- Lock lock;
- BasicLockTestThread thread(&lock);
- PlatformThreadHandle handle;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-
- int acquired = 0;
- for (int i = 0; i < 5; i++) {
- lock.Acquire();
- acquired++;
- lock.Release();
- }
- for (int i = 0; i < 10; i++) {
- lock.Acquire();
- acquired++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
- lock.Release();
- }
- for (int i = 0; i < 10; i++) {
- if (lock.Try()) {
- acquired++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
- lock.Release();
- }
- }
- for (int i = 0; i < 5; i++) {
- lock.Acquire();
- acquired++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 20));
- lock.Release();
- }
-
- PlatformThread::Join(handle);
-
- EXPECT_GE(acquired, 20);
- EXPECT_GE(thread.acquired(), 20);
-}
-
-// Test that Try() works as expected -------------------------------------------
-
-class TryLockTestThread : public PlatformThread::Delegate {
- public:
- explicit TryLockTestThread(Lock* lock) : lock_(lock), got_lock_(false) {}
-
- void ThreadMain() override {
- got_lock_ = lock_->Try();
- if (got_lock_)
- lock_->Release();
- }
-
- bool got_lock() const { return got_lock_; }
-
- private:
- Lock* lock_;
- bool got_lock_;
-
- DISALLOW_COPY_AND_ASSIGN(TryLockTestThread);
-};
-
-TEST(LockTest, TryLock) {
- Lock lock;
-
- ASSERT_TRUE(lock.Try());
- // We now have the lock....
-
- // This thread will not be able to get the lock.
- {
- TryLockTestThread thread(&lock);
- PlatformThreadHandle handle;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-
- PlatformThread::Join(handle);
-
- ASSERT_FALSE(thread.got_lock());
- }
-
- lock.Release();
-
- // This thread will....
- {
- TryLockTestThread thread(&lock);
- PlatformThreadHandle handle;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-
- PlatformThread::Join(handle);
-
- ASSERT_TRUE(thread.got_lock());
- // But it released it....
- ASSERT_TRUE(lock.Try());
- }
-
- lock.Release();
-}
-
-TEST(LockTest, TryTrackedLock) {
- // Enable the activity tracker.
- debug::GlobalActivityTracker::CreateWithLocalMemory(64 << 10, 0, "", 3, 0);
-
- Lock lock;
-
- ASSERT_TRUE(lock.Try());
- // We now have the lock....
-
- // This thread will not be able to get the lock.
- {
- TryLockTestThread thread(&lock);
- PlatformThreadHandle handle;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-
- PlatformThread::Join(handle);
-
- ASSERT_FALSE(thread.got_lock());
- }
-
- lock.Release();
-
- // This thread will....
- {
- TryLockTestThread thread(&lock);
- PlatformThreadHandle handle;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-
- PlatformThread::Join(handle);
-
- ASSERT_TRUE(thread.got_lock());
- // But it released it....
- ASSERT_TRUE(lock.Try());
- }
-
- lock.Release();
- debug::GlobalActivityTracker::ReleaseForTesting();
-}
-
-// Tests that locks actually exclude -------------------------------------------
-
-class MutexLockTestThread : public PlatformThread::Delegate {
- public:
- MutexLockTestThread(Lock* lock, int* value) : lock_(lock), value_(value) {}
-
- // Static helper which can also be called from the main thread.
- static void DoStuff(Lock* lock, int* value) {
- for (int i = 0; i < 40; i++) {
- lock->Acquire();
- int v = *value;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(rand() % 10));
- *value = v + 1;
- lock->Release();
- }
- }
-
- void ThreadMain() override { DoStuff(lock_, value_); }
-
- private:
- Lock* lock_;
- int* value_;
-
- DISALLOW_COPY_AND_ASSIGN(MutexLockTestThread);
-};
-
-TEST(LockTest, MutexTwoThreads) {
- Lock lock;
- int value = 0;
-
- MutexLockTestThread thread(&lock, &value);
- PlatformThreadHandle handle;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
-
- MutexLockTestThread::DoStuff(&lock, &value);
-
- PlatformThread::Join(handle);
-
- EXPECT_EQ(2 * 40, value);
-}
-
-TEST(LockTest, MutexFourThreads) {
- Lock lock;
- int value = 0;
-
- MutexLockTestThread thread1(&lock, &value);
- MutexLockTestThread thread2(&lock, &value);
- MutexLockTestThread thread3(&lock, &value);
- PlatformThreadHandle handle1;
- PlatformThreadHandle handle2;
- PlatformThreadHandle handle3;
-
- ASSERT_TRUE(PlatformThread::Create(0, &thread1, &handle1));
- ASSERT_TRUE(PlatformThread::Create(0, &thread2, &handle2));
- ASSERT_TRUE(PlatformThread::Create(0, &thread3, &handle3));
-
- MutexLockTestThread::DoStuff(&lock, &value);
-
- PlatformThread::Join(handle1);
- PlatformThread::Join(handle2);
- PlatformThread::Join(handle3);
-
- EXPECT_EQ(4 * 40, value);
-}
-
-} // namespace base
diff --git a/base/synchronization/waitable_event_unittest.cc b/base/synchronization/waitable_event_unittest.cc
deleted file mode 100644
index 9c981d8..0000000
--- a/base/synchronization/waitable_event_unittest.cc
+++ /dev/null
@@ -1,274 +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.h"
-
-#include <stddef.h>
-
-#include <algorithm>
-
-#include "base/compiler_specific.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(WaitableEventTest, ManualBasics) {
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- EXPECT_FALSE(event.IsSignaled());
-
- event.Signal();
- EXPECT_TRUE(event.IsSignaled());
- EXPECT_TRUE(event.IsSignaled());
-
- event.Reset();
- EXPECT_FALSE(event.IsSignaled());
- EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
-
- event.Signal();
- event.Wait();
- EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
-}
-
-TEST(WaitableEventTest, ManualInitiallySignaled) {
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::SIGNALED);
-
- EXPECT_TRUE(event.IsSignaled());
- EXPECT_TRUE(event.IsSignaled());
-
- event.Reset();
-
- EXPECT_FALSE(event.IsSignaled());
- EXPECT_FALSE(event.IsSignaled());
-
- event.Signal();
-
- event.Wait();
- EXPECT_TRUE(event.IsSignaled());
- EXPECT_TRUE(event.IsSignaled());
-}
-
-TEST(WaitableEventTest, AutoBasics) {
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- EXPECT_FALSE(event.IsSignaled());
-
- event.Signal();
- EXPECT_TRUE(event.IsSignaled());
- EXPECT_FALSE(event.IsSignaled());
-
- event.Reset();
- EXPECT_FALSE(event.IsSignaled());
- EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
-
- event.Signal();
- event.Wait();
- EXPECT_FALSE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
-
- event.Signal();
- EXPECT_TRUE(event.TimedWait(TimeDelta::FromMilliseconds(10)));
-}
-
-TEST(WaitableEventTest, AutoInitiallySignaled) {
- WaitableEvent event(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::SIGNALED);
-
- EXPECT_TRUE(event.IsSignaled());
- EXPECT_FALSE(event.IsSignaled());
-
- event.Signal();
-
- EXPECT_TRUE(event.IsSignaled());
- EXPECT_FALSE(event.IsSignaled());
-}
-
-TEST(WaitableEventTest, WaitManyShortcut) {
- WaitableEvent* ev[5];
- for (unsigned i = 0; i < 5; ++i) {
- ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- }
-
- ev[3]->Signal();
- EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
-
- ev[3]->Signal();
- EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 3u);
-
- ev[4]->Signal();
- EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 4u);
-
- ev[0]->Signal();
- EXPECT_EQ(WaitableEvent::WaitMany(ev, 5), 0u);
-
- for (unsigned i = 0; i < 5; ++i)
- delete ev[i];
-}
-
-TEST(WaitableEventTest, WaitManyLeftToRight) {
- WaitableEvent* ev[5];
- for (size_t i = 0; i < 5; ++i) {
- ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- }
-
- // Test for consistent left-to-right return behavior across all permutations
- // of the input array. This is to verify that only the indices -- and not
- // the WaitableEvents' addresses -- are relevant in determining who wins when
- // multiple events are signaled.
-
- std::sort(ev, ev + 5);
- do {
- ev[0]->Signal();
- ev[1]->Signal();
- EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
-
- ev[2]->Signal();
- EXPECT_EQ(1u, WaitableEvent::WaitMany(ev, 5));
- EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
-
- ev[3]->Signal();
- ev[4]->Signal();
- ev[0]->Signal();
- EXPECT_EQ(0u, WaitableEvent::WaitMany(ev, 5));
- EXPECT_EQ(3u, WaitableEvent::WaitMany(ev, 5));
- ev[2]->Signal();
- EXPECT_EQ(2u, WaitableEvent::WaitMany(ev, 5));
- EXPECT_EQ(4u, WaitableEvent::WaitMany(ev, 5));
- } while (std::next_permutation(ev, ev + 5));
-
- for (size_t i = 0; i < 5; ++i)
- delete ev[i];
-}
-
-class WaitableEventSignaler : public PlatformThread::Delegate {
- public:
- WaitableEventSignaler(TimeDelta delay, WaitableEvent* event)
- : delay_(delay),
- event_(event) {
- }
-
- void ThreadMain() override {
- PlatformThread::Sleep(delay_);
- event_->Signal();
- }
-
- private:
- const TimeDelta delay_;
- WaitableEvent* event_;
-};
-
-// Tests that a WaitableEvent can be safely deleted when |Wait| is done without
-// additional synchronization.
-TEST(WaitableEventTest, WaitAndDelete) {
- WaitableEvent* ev =
- new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev);
- PlatformThreadHandle thread;
- PlatformThread::Create(0, &signaler, &thread);
-
- ev->Wait();
- delete ev;
-
- PlatformThread::Join(thread);
-}
-
-// Tests that a WaitableEvent can be safely deleted when |WaitMany| is done
-// without additional synchronization.
-TEST(WaitableEventTest, WaitMany) {
- WaitableEvent* ev[5];
- for (unsigned i = 0; i < 5; ++i) {
- ev[i] = new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- }
-
- WaitableEventSignaler signaler(TimeDelta::FromMilliseconds(10), ev[2]);
- PlatformThreadHandle thread;
- PlatformThread::Create(0, &signaler, &thread);
-
- size_t index = WaitableEvent::WaitMany(ev, 5);
-
- for (unsigned i = 0; i < 5; ++i)
- delete ev[i];
-
- PlatformThread::Join(thread);
- EXPECT_EQ(2u, index);
-}
-
-// Tests that using TimeDelta::Max() on TimedWait() is not the same as passing
-// a timeout of 0. (crbug.com/465948)
-TEST(WaitableEventTest, TimedWait) {
- WaitableEvent* ev =
- new WaitableEvent(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- TimeDelta thread_delay = TimeDelta::FromMilliseconds(10);
- WaitableEventSignaler signaler(thread_delay, ev);
- PlatformThreadHandle thread;
- TimeTicks start = TimeTicks::Now();
- PlatformThread::Create(0, &signaler, &thread);
-
- EXPECT_TRUE(ev->TimedWait(TimeDelta::Max()));
- EXPECT_GE(TimeTicks::Now() - start, thread_delay);
- delete ev;
-
- PlatformThread::Join(thread);
-}
-
-// Tests that a sub-ms TimedWait doesn't time out promptly.
-TEST(WaitableEventTest, SubMsTimedWait) {
- WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- TimeDelta delay = TimeDelta::FromMicroseconds(900);
- TimeTicks start_time = TimeTicks::Now();
- ev.TimedWait(delay);
- EXPECT_GE(TimeTicks::Now() - start_time, delay);
-}
-
-// Tests that TimedWaitUntil can be safely used with various end_time deadline
-// values.
-TEST(WaitableEventTest, TimedWaitUntil) {
- WaitableEvent ev(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- TimeTicks start_time(TimeTicks::Now());
- TimeDelta delay = TimeDelta::FromMilliseconds(10);
-
- // Should be OK to wait for the current time or time in the past.
- // That should end promptly and be equivalent to IsSignalled.
- EXPECT_FALSE(ev.TimedWaitUntil(start_time));
- EXPECT_FALSE(ev.TimedWaitUntil(start_time - delay));
-
- // Should be OK to wait for zero TimeTicks().
- EXPECT_FALSE(ev.TimedWaitUntil(TimeTicks()));
-
- // Waiting for a time in the future shouldn't end before the deadline
- // if the event isn't signalled.
- EXPECT_FALSE(ev.TimedWaitUntil(start_time + delay));
- EXPECT_GE(TimeTicks::Now() - start_time, delay);
-
- // Test that passing TimeTicks::Max to TimedWaitUntil is valid and isn't
- // the same as passing TimeTicks(). Also verifies that signaling event
- // ends the wait promptly.
- WaitableEventSignaler signaler(delay, &ev);
- PlatformThreadHandle thread;
- start_time = TimeTicks::Now();
- PlatformThread::Create(0, &signaler, &thread);
-
- EXPECT_TRUE(ev.TimedWaitUntil(TimeTicks::Max()));
- EXPECT_GE(TimeTicks::Now() - start_time, delay);
-
- PlatformThread::Join(thread);
-}
-
-} // 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 bdb45a3..0000000
--- 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_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(¤t_run_loop), Unretained(&counter1)),
- SequencedTaskRunnerHandle::Get());
-
- WaitableEventWatcher watcher2;
- watcher2.StartWatching(
- &event,
- BindOnce(callback, Unretained(¤t_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 f5bad31..0000000
--- 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_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_unittest.cc b/base/sys_info_unittest.cc
deleted file mode 100644
index 7b2c458..0000000
--- a/base/sys_info_unittest.cc
+++ /dev/null
@@ -1,212 +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 <stdint.h>
-
-#include "base/environment.h"
-#include "base/files/file_util.h"
-#include "base/process/process_metrics.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_split.h"
-#include "base/sys_info.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-namespace base {
-
-using SysInfoTest = PlatformTest;
-
-TEST_F(SysInfoTest, NumProcs) {
- // We aren't actually testing that it's correct, just that it's sane.
- EXPECT_GE(SysInfo::NumberOfProcessors(), 1);
-}
-
-TEST_F(SysInfoTest, AmountOfMem) {
- // We aren't actually testing that it's correct, just that it's sane.
- EXPECT_GT(SysInfo::AmountOfPhysicalMemory(), 0);
- EXPECT_GT(SysInfo::AmountOfPhysicalMemoryMB(), 0);
- // The maxmimal amount of virtual memory can be zero which means unlimited.
- EXPECT_GE(SysInfo::AmountOfVirtualMemory(), 0);
-}
-
-#if defined(OS_LINUX) || defined(OS_ANDROID)
-#if defined(OS_LINUX)
-#define MAYBE_AmountOfAvailablePhysicalMemory \
- DISABLED_AmountOfAvailablePhysicalMemory
-#else
-#define MAYBE_AmountOfAvailablePhysicalMemory AmountOfAvailablePhysicalMemory
-#endif // defined(OS_LINUX)
-TEST_F(SysInfoTest, MAYBE_AmountOfAvailablePhysicalMemory) {
- // Note: info is in _K_bytes.
- SystemMemoryInfoKB info;
- ASSERT_TRUE(GetSystemMemoryInfo(&info));
- EXPECT_GT(info.free, 0);
-
- if (info.available != 0) {
- // If there is MemAvailable from kernel.
- EXPECT_LT(info.available, info.total);
- const int64_t amount = SysInfo::AmountOfAvailablePhysicalMemory(info);
- // We aren't actually testing that it's correct, just that it's sane.
- EXPECT_GT(amount, static_cast<int64_t>(info.free) * 1024);
- EXPECT_LT(amount / 1024, info.available);
- // Simulate as if there is no MemAvailable.
- info.available = 0;
- }
-
- // There is no MemAvailable. Check the fallback logic.
- const int64_t amount = SysInfo::AmountOfAvailablePhysicalMemory(info);
- // We aren't actually testing that it's correct, just that it's sane.
- EXPECT_GT(amount, static_cast<int64_t>(info.free) * 1024);
- EXPECT_LT(amount / 1024, info.total);
-}
-#endif // defined(OS_LINUX) || defined(OS_ANDROID)
-
-TEST_F(SysInfoTest, AmountOfFreeDiskSpace) {
- // We aren't actually testing that it's correct, just that it's sane.
- FilePath tmp_path;
- ASSERT_TRUE(GetTempDir(&tmp_path));
- EXPECT_GE(SysInfo::AmountOfFreeDiskSpace(tmp_path), 0) << tmp_path.value();
-}
-
-TEST_F(SysInfoTest, AmountOfTotalDiskSpace) {
- // We aren't actually testing that it's correct, just that it's sane.
- FilePath tmp_path;
- ASSERT_TRUE(GetTempDir(&tmp_path));
- EXPECT_GT(SysInfo::AmountOfTotalDiskSpace(tmp_path), 0) << tmp_path.value();
-}
-
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
-TEST_F(SysInfoTest, OperatingSystemVersionNumbers) {
- int32_t os_major_version = -1;
- int32_t os_minor_version = -1;
- int32_t os_bugfix_version = -1;
- SysInfo::OperatingSystemVersionNumbers(&os_major_version,
- &os_minor_version,
- &os_bugfix_version);
- EXPECT_GT(os_major_version, -1);
- EXPECT_GT(os_minor_version, -1);
- EXPECT_GT(os_bugfix_version, -1);
-}
-#endif
-
-TEST_F(SysInfoTest, Uptime) {
- TimeDelta up_time_1 = SysInfo::Uptime();
- // UpTime() is implemented internally using TimeTicks::Now(), which documents
- // system resolution as being 1-15ms. Sleep a little longer than that.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(20));
- TimeDelta up_time_2 = SysInfo::Uptime();
- EXPECT_GT(up_time_1.InMicroseconds(), 0);
- EXPECT_GT(up_time_2.InMicroseconds(), up_time_1.InMicroseconds());
-}
-
-#if defined(OS_MACOSX)
-TEST_F(SysInfoTest, HardwareModelNameFormatMacAndiOS) {
- std::string hardware_model = SysInfo::HardwareModelName();
- ASSERT_FALSE(hardware_model.empty());
- // Check that the model is of the expected format "Foo,Bar" where "Bar" is
- // a number.
- std::vector<StringPiece> pieces =
- SplitStringPiece(hardware_model, ",", KEEP_WHITESPACE, SPLIT_WANT_ALL);
- ASSERT_EQ(2u, pieces.size()) << hardware_model;
- int value;
- EXPECT_TRUE(StringToInt(pieces[1], &value)) << hardware_model;
-}
-#endif
-
-#if defined(OS_CHROMEOS)
-
-TEST_F(SysInfoTest, GoogleChromeOSVersionNumbers) {
- int32_t os_major_version = -1;
- int32_t os_minor_version = -1;
- int32_t os_bugfix_version = -1;
- const char kLsbRelease[] =
- "FOO=1234123.34.5\n"
- "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, Time());
- SysInfo::OperatingSystemVersionNumbers(&os_major_version,
- &os_minor_version,
- &os_bugfix_version);
- EXPECT_EQ(1, os_major_version);
- EXPECT_EQ(2, os_minor_version);
- EXPECT_EQ(3, os_bugfix_version);
-}
-
-TEST_F(SysInfoTest, GoogleChromeOSVersionNumbersFirst) {
- int32_t os_major_version = -1;
- int32_t os_minor_version = -1;
- int32_t os_bugfix_version = -1;
- const char kLsbRelease[] =
- "CHROMEOS_RELEASE_VERSION=1.2.3.4\n"
- "FOO=1234123.34.5\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, Time());
- SysInfo::OperatingSystemVersionNumbers(&os_major_version,
- &os_minor_version,
- &os_bugfix_version);
- EXPECT_EQ(1, os_major_version);
- EXPECT_EQ(2, os_minor_version);
- EXPECT_EQ(3, os_bugfix_version);
-}
-
-TEST_F(SysInfoTest, GoogleChromeOSNoVersionNumbers) {
- int32_t os_major_version = -1;
- int32_t os_minor_version = -1;
- int32_t os_bugfix_version = -1;
- const char kLsbRelease[] = "FOO=1234123.34.5\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, Time());
- SysInfo::OperatingSystemVersionNumbers(&os_major_version,
- &os_minor_version,
- &os_bugfix_version);
- EXPECT_EQ(0, os_major_version);
- EXPECT_EQ(0, os_minor_version);
- EXPECT_EQ(0, os_bugfix_version);
-}
-
-TEST_F(SysInfoTest, GoogleChromeOSLsbReleaseTime) {
- const char kLsbRelease[] = "CHROMEOS_RELEASE_VERSION=1.2.3.4";
- // Use a fake time that can be safely displayed as a string.
- const Time lsb_release_time(Time::FromDoubleT(12345.6));
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease, lsb_release_time);
- Time parsed_lsb_release_time = SysInfo::GetLsbReleaseTime();
- EXPECT_DOUBLE_EQ(lsb_release_time.ToDoubleT(),
- parsed_lsb_release_time.ToDoubleT());
-}
-
-TEST_F(SysInfoTest, IsRunningOnChromeOS) {
- SysInfo::SetChromeOSVersionInfoForTest("", Time());
- EXPECT_FALSE(SysInfo::IsRunningOnChromeOS());
-
- const char kLsbRelease1[] =
- "CHROMEOS_RELEASE_NAME=Non Chrome OS\n"
- "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease1, Time());
- EXPECT_FALSE(SysInfo::IsRunningOnChromeOS());
-
- const char kLsbRelease2[] =
- "CHROMEOS_RELEASE_NAME=Chrome OS\n"
- "CHROMEOS_RELEASE_VERSION=1.2.3.4\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease2, Time());
- EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
-
- const char kLsbRelease3[] =
- "CHROMEOS_RELEASE_NAME=Chromium OS\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease3, Time());
- EXPECT_TRUE(SysInfo::IsRunningOnChromeOS());
-}
-
-TEST_F(SysInfoTest, GetStrippedReleaseBoard) {
- const char* kLsbRelease1 = "CHROMEOS_RELEASE_BOARD=Glimmer\n";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease1, Time());
- EXPECT_EQ("glimmer", SysInfo::GetStrippedReleaseBoard());
-
- const char* kLsbRelease2 = "CHROMEOS_RELEASE_BOARD=glimmer-signed-mp-v4keys";
- SysInfo::SetChromeOSVersionInfoForTest(kLsbRelease2, Time());
- EXPECT_EQ("glimmer", SysInfo::GetStrippedReleaseBoard());
-}
-
-#endif // OS_CHROMEOS
-
-} // namespace base
diff --git a/base/system_monitor/system_monitor_unittest.cc b/base/system_monitor/system_monitor_unittest.cc
deleted file mode 100644
index 8963f7b..0000000
--- 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/cancelable_task_tracker_unittest.cc b/base/task/cancelable_task_tracker_unittest.cc
deleted file mode 100644
index c75adc4..0000000
--- a/base/task/cancelable_task_tracker_unittest.cc
+++ /dev/null
@@ -1,403 +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/task/cancelable_task_tracker.h"
-
-#include <cstddef>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/logging.h"
-#include "base/memory/ref_counted.h"
-#include "base/memory/weak_ptr.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class CancelableTaskTrackerTest : public testing::Test {
- protected:
- ~CancelableTaskTrackerTest() override { RunCurrentLoopUntilIdle(); }
-
- void RunCurrentLoopUntilIdle() {
- RunLoop run_loop;
- run_loop.RunUntilIdle();
- }
-
- CancelableTaskTracker task_tracker_;
-
- private:
- // Needed by CancelableTaskTracker methods.
- MessageLoop message_loop_;
-};
-
-void AddFailureAt(const Location& location) {
- ADD_FAILURE_AT(location.file_name(), location.line_number());
-}
-
-// Returns a closure that fails if run.
-Closure MakeExpectedNotRunClosure(const Location& location) {
- return Bind(&AddFailureAt, location);
-}
-
-// A helper class for MakeExpectedRunClosure() that fails if it is
-// destroyed without Run() having been called. This class may be used
-// from multiple threads as long as Run() is called at most once
-// before destruction.
-class RunChecker {
- public:
- explicit RunChecker(const Location& location)
- : location_(location), called_(false) {}
-
- ~RunChecker() {
- if (!called_) {
- ADD_FAILURE_AT(location_.file_name(), location_.line_number());
- }
- }
-
- void Run() { called_ = true; }
-
- private:
- Location location_;
- bool called_;
-};
-
-// Returns a closure that fails on destruction if it hasn't been run.
-Closure MakeExpectedRunClosure(const Location& location) {
- return Bind(&RunChecker::Run, Owned(new RunChecker(location)));
-}
-
-} // namespace
-
-// With the task tracker, post a task, a task with a reply, and get a
-// new task id without canceling any of them. The tasks and the reply
-// should run and the "is canceled" callback should return false.
-TEST_F(CancelableTaskTrackerTest, NoCancel) {
- Thread worker_thread("worker thread");
- ASSERT_TRUE(worker_thread.Start());
-
- ignore_result(task_tracker_.PostTask(worker_thread.task_runner().get(),
- FROM_HERE,
- MakeExpectedRunClosure(FROM_HERE)));
-
- ignore_result(task_tracker_.PostTaskAndReply(
- worker_thread.task_runner().get(), FROM_HERE,
- MakeExpectedRunClosure(FROM_HERE), MakeExpectedRunClosure(FROM_HERE)));
-
- CancelableTaskTracker::IsCanceledCallback is_canceled;
- ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
-
- worker_thread.Stop();
-
- RunCurrentLoopUntilIdle();
-
- EXPECT_FALSE(is_canceled.Run());
-}
-
-// Post a task with the task tracker but cancel it before running the
-// task runner. The task should not run.
-TEST_F(CancelableTaskTrackerTest, CancelPostedTask) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- CancelableTaskTracker::TaskId task_id = task_tracker_.PostTask(
- test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE));
- EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
-
- EXPECT_EQ(1U, test_task_runner->NumPendingTasks());
-
- task_tracker_.TryCancel(task_id);
-
- test_task_runner->RunUntilIdle();
-}
-
-// Post a task with reply with the task tracker and cancel it before
-// running the task runner. Neither the task nor the reply should
-// run.
-TEST_F(CancelableTaskTrackerTest, CancelPostedTaskAndReply) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- CancelableTaskTracker::TaskId task_id =
- task_tracker_.PostTaskAndReply(test_task_runner.get(),
- FROM_HERE,
- MakeExpectedNotRunClosure(FROM_HERE),
- MakeExpectedNotRunClosure(FROM_HERE));
- EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
-
- task_tracker_.TryCancel(task_id);
-
- test_task_runner->RunUntilIdle();
-}
-
-// Post a task with reply with the task tracker and cancel it after
-// running the task runner but before running the current message
-// loop. The task should run but the reply should not.
-TEST_F(CancelableTaskTrackerTest, CancelReply) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- CancelableTaskTracker::TaskId task_id =
- task_tracker_.PostTaskAndReply(test_task_runner.get(),
- FROM_HERE,
- MakeExpectedRunClosure(FROM_HERE),
- MakeExpectedNotRunClosure(FROM_HERE));
- EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
-
- test_task_runner->RunUntilIdle();
-
- task_tracker_.TryCancel(task_id);
-}
-
-// Post a task with reply with the task tracker on a worker thread and
-// cancel it before running the current message loop. The task should
-// run but the reply should not.
-TEST_F(CancelableTaskTrackerTest, CancelReplyDifferentThread) {
- Thread worker_thread("worker thread");
- ASSERT_TRUE(worker_thread.Start());
-
- CancelableTaskTracker::TaskId task_id = task_tracker_.PostTaskAndReply(
- worker_thread.task_runner().get(), FROM_HERE, DoNothing(),
- MakeExpectedNotRunClosure(FROM_HERE));
- EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
-
- task_tracker_.TryCancel(task_id);
-
- worker_thread.Stop();
-}
-
-void ExpectIsCanceled(
- const CancelableTaskTracker::IsCanceledCallback& is_canceled,
- bool expected_is_canceled) {
- EXPECT_EQ(expected_is_canceled, is_canceled.Run());
-}
-
-// Create a new task ID and check its status on a separate thread
-// before and after canceling. The is-canceled callback should be
-// thread-safe (i.e., nothing should blow up).
-TEST_F(CancelableTaskTrackerTest, NewTrackedTaskIdDifferentThread) {
- CancelableTaskTracker::IsCanceledCallback is_canceled;
- CancelableTaskTracker::TaskId task_id =
- task_tracker_.NewTrackedTaskId(&is_canceled);
-
- EXPECT_FALSE(is_canceled.Run());
-
- Thread other_thread("other thread");
- ASSERT_TRUE(other_thread.Start());
- other_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&ExpectIsCanceled, is_canceled, false));
- other_thread.Stop();
-
- task_tracker_.TryCancel(task_id);
-
- ASSERT_TRUE(other_thread.Start());
- other_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&ExpectIsCanceled, is_canceled, true));
- other_thread.Stop();
-}
-
-// With the task tracker, post a task, a task with a reply, get a new
-// task id, and then cancel all of them. None of the tasks nor the
-// reply should run and the "is canceled" callback should return
-// true.
-TEST_F(CancelableTaskTrackerTest, CancelAll) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- ignore_result(task_tracker_.PostTask(
- test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
-
- ignore_result(
- task_tracker_.PostTaskAndReply(test_task_runner.get(),
- FROM_HERE,
- MakeExpectedNotRunClosure(FROM_HERE),
- MakeExpectedNotRunClosure(FROM_HERE)));
-
- CancelableTaskTracker::IsCanceledCallback is_canceled;
- ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
-
- task_tracker_.TryCancelAll();
-
- test_task_runner->RunUntilIdle();
-
- RunCurrentLoopUntilIdle();
-
- EXPECT_TRUE(is_canceled.Run());
-}
-
-// With the task tracker, post a task, a task with a reply, get a new
-// task id, and then cancel all of them. None of the tasks nor the
-// reply should run and the "is canceled" callback should return
-// true.
-TEST_F(CancelableTaskTrackerTest, DestructionCancelsAll) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- CancelableTaskTracker::IsCanceledCallback is_canceled;
-
- {
- // Create another task tracker with a smaller scope.
- CancelableTaskTracker task_tracker;
-
- ignore_result(task_tracker.PostTask(test_task_runner.get(),
- FROM_HERE,
- MakeExpectedNotRunClosure(FROM_HERE)));
-
- ignore_result(
- task_tracker.PostTaskAndReply(test_task_runner.get(),
- FROM_HERE,
- MakeExpectedNotRunClosure(FROM_HERE),
- MakeExpectedNotRunClosure(FROM_HERE)));
-
- ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
- }
-
- test_task_runner->RunUntilIdle();
-
- RunCurrentLoopUntilIdle();
-
- EXPECT_FALSE(is_canceled.Run());
-}
-
-// Post a task and cancel it. HasTrackedTasks() should return false as soon as
-// TryCancelAll() is called.
-TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPost) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- EXPECT_FALSE(task_tracker_.HasTrackedTasks());
-
- ignore_result(task_tracker_.PostTask(
- test_task_runner.get(), FROM_HERE, MakeExpectedNotRunClosure(FROM_HERE)));
-
- task_tracker_.TryCancelAll();
-
- EXPECT_FALSE(task_tracker_.HasTrackedTasks());
-
- test_task_runner->RunUntilIdle();
- RunCurrentLoopUntilIdle();
-}
-
-// Post a task with a reply and cancel it. HasTrackedTasks() should return false
-// as soon as TryCancelAll() is called.
-TEST_F(CancelableTaskTrackerTest, HasTrackedTasksPostWithReply) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- EXPECT_FALSE(task_tracker_.HasTrackedTasks());
-
- ignore_result(
- task_tracker_.PostTaskAndReply(test_task_runner.get(),
- FROM_HERE,
- MakeExpectedNotRunClosure(FROM_HERE),
- MakeExpectedNotRunClosure(FROM_HERE)));
-
- task_tracker_.TryCancelAll();
-
- EXPECT_FALSE(task_tracker_.HasTrackedTasks());
-
- test_task_runner->RunUntilIdle();
- RunCurrentLoopUntilIdle();
-}
-
-// Create a new tracked task ID. HasTrackedTasks() should return false as soon
-// as TryCancelAll() is called.
-TEST_F(CancelableTaskTrackerTest, HasTrackedTasksIsCancelled) {
- EXPECT_FALSE(task_tracker_.HasTrackedTasks());
-
- CancelableTaskTracker::IsCanceledCallback is_canceled;
- ignore_result(task_tracker_.NewTrackedTaskId(&is_canceled));
-
- task_tracker_.TryCancelAll();
-
- EXPECT_FALSE(task_tracker_.HasTrackedTasks());
-}
-
-// The death tests below make sure that calling task tracker member
-// functions from a thread different from its owner thread DCHECKs in
-// debug mode.
-
-class CancelableTaskTrackerDeathTest : public CancelableTaskTrackerTest {
- protected:
- CancelableTaskTrackerDeathTest() {
- // The default style "fast" does not support multi-threaded tests.
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- }
-};
-
-// Runs |fn| with |task_tracker|, expecting it to crash in debug mode.
-void MaybeRunDeadlyTaskTrackerMemberFunction(
- CancelableTaskTracker* task_tracker,
- const Callback<void(CancelableTaskTracker*)>& fn) {
- EXPECT_DCHECK_DEATH(fn.Run(task_tracker));
-}
-
-void PostDoNothingTask(CancelableTaskTracker* task_tracker) {
- ignore_result(task_tracker->PostTask(
- scoped_refptr<TestSimpleTaskRunner>(new TestSimpleTaskRunner()).get(),
- FROM_HERE, DoNothing()));
-}
-
-TEST_F(CancelableTaskTrackerDeathTest, PostFromDifferentThread) {
- Thread bad_thread("bad thread");
- ASSERT_TRUE(bad_thread.Start());
-
- bad_thread.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&MaybeRunDeadlyTaskTrackerMemberFunction,
- Unretained(&task_tracker_), Bind(&PostDoNothingTask)));
-}
-
-void TryCancel(CancelableTaskTracker::TaskId task_id,
- CancelableTaskTracker* task_tracker) {
- task_tracker->TryCancel(task_id);
-}
-
-TEST_F(CancelableTaskTrackerDeathTest, CancelOnDifferentThread) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- Thread bad_thread("bad thread");
- ASSERT_TRUE(bad_thread.Start());
-
- CancelableTaskTracker::TaskId task_id =
- task_tracker_.PostTask(test_task_runner.get(), FROM_HERE, DoNothing());
- EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
-
- bad_thread.task_runner()->PostTask(
- FROM_HERE,
- BindOnce(&MaybeRunDeadlyTaskTrackerMemberFunction,
- Unretained(&task_tracker_), Bind(&TryCancel, task_id)));
-
- test_task_runner->RunUntilIdle();
-}
-
-TEST_F(CancelableTaskTrackerDeathTest, CancelAllOnDifferentThread) {
- scoped_refptr<TestSimpleTaskRunner> test_task_runner(
- new TestSimpleTaskRunner());
-
- Thread bad_thread("bad thread");
- ASSERT_TRUE(bad_thread.Start());
-
- CancelableTaskTracker::TaskId task_id =
- task_tracker_.PostTask(test_task_runner.get(), FROM_HERE, DoNothing());
- EXPECT_NE(CancelableTaskTracker::kBadTaskId, task_id);
-
- bad_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&MaybeRunDeadlyTaskTrackerMemberFunction,
- Unretained(&task_tracker_),
- Bind(&CancelableTaskTracker::TryCancelAll)));
-
- test_task_runner->RunUntilIdle();
-}
-
-} // namespace base
diff --git a/base/task_runner_util_unittest.cc b/base/task_runner_util_unittest.cc
deleted file mode 100644
index 44baad4..0000000
--- a/base/task_runner_util_unittest.cc
+++ /dev/null
@@ -1,125 +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/task_runner_util.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-int ReturnFourtyTwo() {
- return 42;
-}
-
-void StoreValue(int* destination, int value) {
- *destination = value;
-}
-
-void StoreDoubleValue(double* destination, double value) {
- *destination = value;
-}
-
-int g_foo_destruct_count = 0;
-int g_foo_free_count = 0;
-
-struct Foo {
- ~Foo() {
- ++g_foo_destruct_count;
- }
-};
-
-std::unique_ptr<Foo> CreateFoo() {
- return std::unique_ptr<Foo>(new Foo);
-}
-
-void ExpectFoo(std::unique_ptr<Foo> foo) {
- EXPECT_TRUE(foo.get());
- std::unique_ptr<Foo> local_foo(std::move(foo));
- EXPECT_TRUE(local_foo.get());
- EXPECT_FALSE(foo.get());
-}
-
-struct FooDeleter {
- void operator()(Foo* foo) const {
- ++g_foo_free_count;
- delete foo;
- };
-};
-
-std::unique_ptr<Foo, FooDeleter> CreateScopedFoo() {
- return std::unique_ptr<Foo, FooDeleter>(new Foo);
-}
-
-void ExpectScopedFoo(std::unique_ptr<Foo, FooDeleter> foo) {
- EXPECT_TRUE(foo.get());
- std::unique_ptr<Foo, FooDeleter> local_foo(std::move(foo));
- EXPECT_TRUE(local_foo.get());
- EXPECT_FALSE(foo.get());
-}
-
-} // namespace
-
-TEST(TaskRunnerHelpersTest, PostTaskAndReplyWithResult) {
- int result = 0;
-
- MessageLoop message_loop;
- PostTaskAndReplyWithResult(message_loop.task_runner().get(), FROM_HERE,
- Bind(&ReturnFourtyTwo),
- Bind(&StoreValue, &result));
-
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(42, result);
-}
-
-TEST(TaskRunnerHelpersTest, PostTaskAndReplyWithResultImplicitConvert) {
- double result = 0;
-
- MessageLoop message_loop;
- PostTaskAndReplyWithResult(message_loop.task_runner().get(), FROM_HERE,
- Bind(&ReturnFourtyTwo),
- Bind(&StoreDoubleValue, &result));
-
- RunLoop().RunUntilIdle();
-
- EXPECT_DOUBLE_EQ(42.0, result);
-}
-
-TEST(TaskRunnerHelpersTest, PostTaskAndReplyWithResultPassed) {
- g_foo_destruct_count = 0;
- g_foo_free_count = 0;
-
- MessageLoop message_loop;
- PostTaskAndReplyWithResult(message_loop.task_runner().get(), FROM_HERE,
- Bind(&CreateFoo), Bind(&ExpectFoo));
-
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, g_foo_destruct_count);
- EXPECT_EQ(0, g_foo_free_count);
-}
-
-TEST(TaskRunnerHelpersTest, PostTaskAndReplyWithResultPassedFreeProc) {
- g_foo_destruct_count = 0;
- g_foo_free_count = 0;
-
- MessageLoop message_loop;
- PostTaskAndReplyWithResult(message_loop.task_runner().get(), FROM_HERE,
- Bind(&CreateScopedFoo), Bind(&ExpectScopedFoo));
-
- RunLoop().RunUntilIdle();
-
- EXPECT_EQ(1, g_foo_destruct_count);
- EXPECT_EQ(1, g_foo_free_count);
-}
-
-} // 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 67c797a..0000000
--- 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/lazy_task_runner_unittest.cc b/base/task_scheduler/lazy_task_runner_unittest.cc
deleted file mode 100644
index e898a1e..0000000
--- a/base/task_scheduler/lazy_task_runner_unittest.cc
+++ /dev/null
@@ -1,199 +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/lazy_task_runner.h"
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/sequence_checker_impl.h"
-#include "base/task_scheduler/scoped_set_task_priority_for_current_thread.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/threading/thread_checker_impl.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include "base/win/com_init_util.h"
-#endif
-
-namespace base {
-
-namespace {
-
-LazySequencedTaskRunner g_sequenced_task_runner_user_visible =
- LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({TaskPriority::USER_VISIBLE});
-LazySequencedTaskRunner g_sequenced_task_runner_user_blocking =
- LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({TaskPriority::USER_BLOCKING});
-
-LazySingleThreadTaskRunner g_single_thread_task_runner_user_visible =
- LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
- {TaskPriority::USER_VISIBLE},
- SingleThreadTaskRunnerThreadMode::SHARED);
-LazySingleThreadTaskRunner g_single_thread_task_runner_user_blocking =
- LAZY_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(
- {TaskPriority::USER_BLOCKING},
- SingleThreadTaskRunnerThreadMode::SHARED);
-
-#if defined(OS_WIN)
-LazyCOMSTATaskRunner g_com_sta_task_runner_user_visible =
- LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
- {TaskPriority::USER_VISIBLE},
- SingleThreadTaskRunnerThreadMode::SHARED);
-LazyCOMSTATaskRunner g_com_sta_task_runner_user_blocking =
- LAZY_COM_STA_TASK_RUNNER_INITIALIZER(
- {TaskPriority::USER_BLOCKING},
- SingleThreadTaskRunnerThreadMode::SHARED);
-#endif // defined(OS_WIN)
-
-void InitCheckers(SequenceCheckerImpl* sequence_checker,
- ThreadCheckerImpl* thread_checker) {
- sequence_checker->DetachFromSequence();
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
- thread_checker->DetachFromThread();
- EXPECT_TRUE(thread_checker->CalledOnValidThread());
-}
-
-void ExpectSequencedEnvironment(SequenceCheckerImpl* sequence_checker,
- ThreadCheckerImpl* thread_checker,
- TaskPriority expected_priority) {
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
- EXPECT_FALSE(thread_checker->CalledOnValidThread());
- EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
-}
-
-void ExpectSingleThreadEnvironment(SequenceCheckerImpl* sequence_checker,
- ThreadCheckerImpl* thread_checker,
- TaskPriority expected_priority
-#if defined(OS_WIN)
- ,
- bool expect_com_sta = false
-#endif
- ) {
- EXPECT_TRUE(sequence_checker->CalledOnValidSequence());
- EXPECT_TRUE(thread_checker->CalledOnValidThread());
- EXPECT_EQ(expected_priority, internal::GetTaskPriorityForCurrentThread());
-
-#if defined(OS_WIN)
- if (expect_com_sta)
- win::AssertComApartmentType(win::ComApartmentType::STA);
-#endif
-}
-
-class TaskSchedulerLazyTaskRunnerEnvironmentTest : public testing::Test {
- protected:
- TaskSchedulerLazyTaskRunnerEnvironmentTest() = default;
-
- void TestTaskRunnerEnvironment(scoped_refptr<SequencedTaskRunner> task_runner,
- bool expect_single_thread,
- TaskPriority expected_priority
-#if defined(OS_WIN)
- ,
- bool expect_com_sta = false
-#endif
- ) {
- SequenceCheckerImpl sequence_checker;
- ThreadCheckerImpl thread_checker;
- task_runner->PostTask(FROM_HERE,
- BindOnce(&InitCheckers, Unretained(&sequence_checker),
- Unretained(&thread_checker)));
- scoped_task_environment_.RunUntilIdle();
-
- OnceClosure task =
- expect_single_thread
- ? BindOnce(&ExpectSingleThreadEnvironment,
- Unretained(&sequence_checker),
- Unretained(&thread_checker), expected_priority
-#if defined(OS_WIN)
- ,
- expect_com_sta
-#endif
- )
- : BindOnce(&ExpectSequencedEnvironment,
- Unretained(&sequence_checker),
- Unretained(&thread_checker), expected_priority);
- task_runner->PostTask(FROM_HERE, std::move(task));
- scoped_task_environment_.RunUntilIdle();
- }
-
- test::ScopedTaskEnvironment scoped_task_environment_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerLazyTaskRunnerEnvironmentTest);
-};
-
-} // namespace
-
-TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
- LazySequencedTaskRunnerUserVisible) {
- TestTaskRunnerEnvironment(g_sequenced_task_runner_user_visible.Get(), false,
- TaskPriority::USER_VISIBLE);
-}
-
-TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
- LazySequencedTaskRunnerUserBlocking) {
- TestTaskRunnerEnvironment(g_sequenced_task_runner_user_blocking.Get(), false,
- TaskPriority::USER_BLOCKING);
-}
-
-TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
- LazySingleThreadTaskRunnerUserVisible) {
- TestTaskRunnerEnvironment(g_single_thread_task_runner_user_visible.Get(),
- true, TaskPriority::USER_VISIBLE);
-}
-
-TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
- LazySingleThreadTaskRunnerUserBlocking) {
- TestTaskRunnerEnvironment(g_single_thread_task_runner_user_blocking.Get(),
- true, TaskPriority::USER_BLOCKING);
-}
-
-#if defined(OS_WIN)
-TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
- LazyCOMSTATaskRunnerUserVisible) {
- TestTaskRunnerEnvironment(g_com_sta_task_runner_user_visible.Get(), true,
- TaskPriority::USER_VISIBLE, true);
-}
-
-TEST_F(TaskSchedulerLazyTaskRunnerEnvironmentTest,
- LazyCOMSTATaskRunnerUserBlocking) {
- TestTaskRunnerEnvironment(g_com_sta_task_runner_user_blocking.Get(), true,
- TaskPriority::USER_BLOCKING, true);
-}
-#endif // defined(OS_WIN)
-
-TEST(TaskSchdulerLazyTaskRunnerTest, LazySequencedTaskRunnerReset) {
- for (int i = 0; i < 2; ++i) {
- test::ScopedTaskEnvironment scoped_task_environment;
- // If the TaskRunner isn't released when the test::ScopedTaskEnvironment
- // goes out of scope, the second invocation of the line below will access a
- // deleted TaskScheduler and crash.
- g_sequenced_task_runner_user_visible.Get()->PostTask(FROM_HERE,
- DoNothing());
- }
-}
-
-TEST(TaskSchdulerLazyTaskRunnerTest, LazySingleThreadTaskRunnerReset) {
- for (int i = 0; i < 2; ++i) {
- test::ScopedTaskEnvironment scoped_task_environment;
- // If the TaskRunner isn't released when the test::ScopedTaskEnvironment
- // goes out of scope, the second invocation of the line below will access a
- // deleted TaskScheduler and crash.
- g_single_thread_task_runner_user_visible.Get()->PostTask(FROM_HERE,
- DoNothing());
- }
-}
-
-#if defined(OS_WIN)
-TEST(TaskSchdulerLazyTaskRunnerTest, LazyCOMSTATaskRunnerReset) {
- for (int i = 0; i < 2; ++i) {
- test::ScopedTaskEnvironment scoped_task_environment;
- // If the TaskRunner isn't released when the test::ScopedTaskEnvironment
- // goes out of scope, the second invocation of the line below will access a
- // deleted TaskScheduler and crash.
- g_com_sta_task_runner_user_visible.Get()->PostTask(FROM_HERE, DoNothing());
- }
-}
-#endif // defined(OS_WIN)
-
-} // namespace base
diff --git a/base/task_scheduler/priority_queue_unittest.cc b/base/task_scheduler/priority_queue_unittest.cc
deleted file mode 100644
index 9dc4d13..0000000
--- a/base/task_scheduler/priority_queue_unittest.cc
+++ /dev/null
@@ -1,172 +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),
- transaction_began_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- // 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_lock_unittest.cc b/base/task_scheduler/scheduler_lock_unittest.cc
deleted file mode 100644
index 5518247..0000000
--- a/base/task_scheduler/scheduler_lock_unittest.cc
+++ /dev/null
@@ -1,296 +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_lock.h"
-
-#include <stdlib.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/rand_util.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-namespace {
-
-// Adapted from base::Lock's BasicLockTestThread to make sure
-// Acquire()/Release() don't crash.
-class BasicLockTestThread : public SimpleThread {
- public:
- explicit BasicLockTestThread(SchedulerLock* lock)
- : SimpleThread("BasicLockTestThread"),
- lock_(lock),
- acquired_(0) {}
-
- int acquired() const { return acquired_; }
-
- private:
- void Run() override {
- for (int i = 0; i < 10; i++) {
- lock_->Acquire();
- acquired_++;
- lock_->Release();
- }
- for (int i = 0; i < 10; i++) {
- lock_->Acquire();
- acquired_++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
- lock_->Release();
- }
- }
-
- SchedulerLock* const lock_;
- int acquired_;
-
- DISALLOW_COPY_AND_ASSIGN(BasicLockTestThread);
-};
-
-class BasicLockAcquireAndWaitThread : public SimpleThread {
- public:
- explicit BasicLockAcquireAndWaitThread(SchedulerLock* lock)
- : SimpleThread("BasicLockAcquireAndWaitThread"),
- lock_(lock),
- lock_acquire_event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- main_thread_continue_event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED) {
- }
-
- void WaitForLockAcquisition() {
- lock_acquire_event_.Wait();
- }
-
- void ContinueMain() {
- main_thread_continue_event_.Signal();
- }
-
- private:
- void Run() override {
- lock_->Acquire();
- lock_acquire_event_.Signal();
- main_thread_continue_event_.Wait();
- lock_->Release();
- }
-
- SchedulerLock* const lock_;
- WaitableEvent lock_acquire_event_;
- WaitableEvent main_thread_continue_event_;
-
- DISALLOW_COPY_AND_ASSIGN(BasicLockAcquireAndWaitThread);
-};
-
-TEST(TaskSchedulerLock, Basic) {
- SchedulerLock lock;
- BasicLockTestThread thread(&lock);
-
- thread.Start();
-
- int acquired = 0;
- for (int i = 0; i < 5; i++) {
- lock.Acquire();
- acquired++;
- lock.Release();
- }
- for (int i = 0; i < 10; i++) {
- lock.Acquire();
- acquired++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
- lock.Release();
- }
- for (int i = 0; i < 5; i++) {
- lock.Acquire();
- acquired++;
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(base::RandInt(0, 19)));
- lock.Release();
- }
-
- thread.Join();
-
- EXPECT_EQ(acquired, 20);
- EXPECT_EQ(thread.acquired(), 20);
-}
-
-TEST(TaskSchedulerLock, AcquirePredecessor) {
- SchedulerLock predecessor;
- SchedulerLock lock(&predecessor);
- predecessor.Acquire();
- lock.Acquire();
- lock.Release();
- predecessor.Release();
-}
-
-TEST(TaskSchedulerLock, AcquirePredecessorWrongOrder) {
- SchedulerLock predecessor;
- SchedulerLock lock(&predecessor);
- EXPECT_DCHECK_DEATH({
- lock.Acquire();
- predecessor.Acquire();
- });
-}
-
-TEST(TaskSchedulerLock, AcquireNonPredecessor) {
- SchedulerLock lock1;
- SchedulerLock lock2;
- EXPECT_DCHECK_DEATH({
- lock1.Acquire();
- lock2.Acquire();
- });
-}
-
-TEST(TaskSchedulerLock, AcquireMultipleLocksInOrder) {
- SchedulerLock lock1;
- SchedulerLock lock2(&lock1);
- SchedulerLock lock3(&lock2);
- lock1.Acquire();
- lock2.Acquire();
- lock3.Acquire();
- lock3.Release();
- lock2.Release();
- lock1.Release();
-}
-
-TEST(TaskSchedulerLock, AcquireMultipleLocksInTheMiddleOfAChain) {
- SchedulerLock lock1;
- SchedulerLock lock2(&lock1);
- SchedulerLock lock3(&lock2);
- lock2.Acquire();
- lock3.Acquire();
- lock3.Release();
- lock2.Release();
-}
-
-TEST(TaskSchedulerLock, AcquireMultipleLocksNoTransitivity) {
- SchedulerLock lock1;
- SchedulerLock lock2(&lock1);
- SchedulerLock lock3(&lock2);
- EXPECT_DCHECK_DEATH({
- lock1.Acquire();
- lock3.Acquire();
- });
-}
-
-TEST(TaskSchedulerLock, AcquireLocksDifferentThreadsSafely) {
- SchedulerLock lock1;
- SchedulerLock lock2;
- BasicLockAcquireAndWaitThread thread(&lock1);
- thread.Start();
-
- lock2.Acquire();
- thread.WaitForLockAcquisition();
- thread.ContinueMain();
- thread.Join();
- lock2.Release();
-}
-
-TEST(TaskSchedulerLock,
- AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorFirst) {
- // A lock and its predecessor may be safely acquired on different threads.
- // This Thread Other Thread
- // predecessor.Acquire()
- // lock.Acquire()
- // predecessor.Release()
- // lock.Release()
- SchedulerLock predecessor;
- SchedulerLock lock(&predecessor);
- predecessor.Acquire();
- BasicLockAcquireAndWaitThread thread(&lock);
- thread.Start();
- thread.WaitForLockAcquisition();
- predecessor.Release();
- thread.ContinueMain();
- thread.Join();
-}
-
-TEST(TaskSchedulerLock,
- AcquireLocksWithPredecessorDifferentThreadsSafelyPredecessorLast) {
- // A lock and its predecessor may be safely acquired on different threads.
- // This Thread Other Thread
- // lock.Acquire()
- // predecessor.Acquire()
- // lock.Release()
- // predecessor.Release()
- SchedulerLock predecessor;
- SchedulerLock lock(&predecessor);
- lock.Acquire();
- BasicLockAcquireAndWaitThread thread(&predecessor);
- thread.Start();
- thread.WaitForLockAcquisition();
- lock.Release();
- thread.ContinueMain();
- thread.Join();
-}
-
-TEST(TaskSchedulerLock,
- AcquireLocksWithPredecessorDifferentThreadsSafelyNoInterference) {
- // Acquisition of an unrelated lock on another thread should not affect a
- // legal lock acquisition with a predecessor on this thread.
- // This Thread Other Thread
- // predecessor.Acquire()
- // unrelated.Acquire()
- // lock.Acquire()
- // unrelated.Release()
- // lock.Release()
- // predecessor.Release();
- SchedulerLock predecessor;
- SchedulerLock lock(&predecessor);
- predecessor.Acquire();
- SchedulerLock unrelated;
- BasicLockAcquireAndWaitThread thread(&unrelated);
- thread.Start();
- thread.WaitForLockAcquisition();
- lock.Acquire();
- thread.ContinueMain();
- thread.Join();
- lock.Release();
- predecessor.Release();
-}
-
-TEST(TaskSchedulerLock, SelfReferentialLock) {
- struct SelfReferentialLock {
- SelfReferentialLock() : lock(&lock) {}
-
- SchedulerLock lock;
- };
-
- EXPECT_DCHECK_DEATH({ SelfReferentialLock lock; });
-}
-
-TEST(TaskSchedulerLock, PredecessorCycle) {
- struct LockCycle {
- LockCycle() : lock1(&lock2), lock2(&lock1) {}
-
- SchedulerLock lock1;
- SchedulerLock lock2;
- };
-
- EXPECT_DCHECK_DEATH({ LockCycle cycle; });
-}
-
-TEST(TaskSchedulerLock, PredecessorLongerCycle) {
- struct LockCycle {
- LockCycle()
- : lock1(&lock5),
- lock2(&lock1),
- lock3(&lock2),
- lock4(&lock3),
- lock5(&lock4) {}
-
- SchedulerLock lock1;
- SchedulerLock lock2;
- SchedulerLock lock3;
- SchedulerLock lock4;
- SchedulerLock lock5;
- };
-
- EXPECT_DCHECK_DEATH({ LockCycle cycle; });
-}
-
-} // namespace
-} // 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 52d99f6..0000000
--- a/base/task_scheduler/scheduler_single_thread_task_runner_manager_unittest.cc
+++ /dev/null
@@ -1,676 +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/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::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_can_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // 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(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- task_runner_normal->PostTask(
- FROM_HERE,
- BindOnce(&WaitableEvent::Signal, Unretained(&waitable_event_normal)));
-
- waitable_event_background.Wait();
- waitable_event_normal.Wait();
-
- if (Lock::HandlesMultipleThreadPriorities() &&
- PlatformThread::CanIncreaseCurrentThreadPriority()) {
- 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),
- run_started_event_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- ~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::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- {
- 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::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_blocking(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- {
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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 21e77f4..0000000
--- a/base/task_scheduler/scheduler_worker_pool_impl_unittest.cc
+++ /dev/null
@@ -1,1566 +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/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/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 "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 kNumWorkersInWorkerPool = 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 worker capacity.
-void WaitWithoutBlockingObserver(WaitableEvent* event) {
- internal::ScopedClearBlockingObserverForTesting clear_blocking_observer;
- event->Wait();
-}
-
-class TaskSchedulerWorkerPoolImplTestBase {
- protected:
- TaskSchedulerWorkerPoolImplTestBase()
- : service_thread_("TaskSchedulerServiceThread"){};
-
- void CommonSetUp() {
- CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool);
- }
-
- void CommonTearDown() {
- service_thread_.Stop();
- task_tracker_.FlushForTesting();
- worker_pool_->WaitForAllWorkersIdleForTesting();
- 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 num_workers) {
- ASSERT_TRUE(worker_pool_);
- worker_pool_->Start(
- SchedulerWorkerPoolParams(num_workers, suggested_reclaim_time),
- service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- }
-
- void CreateAndStartWorkerPool(TimeDelta suggested_reclaim_time,
- size_t num_workers) {
- CreateWorkerPool();
- StartWorkerPool(suggested_reclaim_time, num_workers);
- }
-
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- std::vector<std::unique_ptr<test::TestTaskFactory>> blocked_task_factories;
- for (size_t i = 0; i < (kNumWorkersInWorkerPool - 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 |kNumWorkersInWorkerPool|
- // 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- std::vector<std::unique_ptr<test::TestTaskFactory>> factories;
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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 num_workers) override {
- ASSERT_TRUE(worker_pool_);
- worker_pool_->Start(
- SchedulerWorkerPoolParams(num_workers, suggested_reclaim_time),
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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 TaskSchedulerWorkerPoolImplPostTaskBeforeStartTest
- : 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(TaskSchedulerWorkerPoolImplPostTaskBeforeStartTest,
- PostTasksBeforeStart) {
- PlatformThreadRef task_1_thread_ref;
- PlatformThreadRef task_2_thread_ref;
- WaitableEvent task_1_running(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_2_running(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- 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(), kNumWorkersInWorkerPool);
-
- // 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 |worker_capacity_| during Start.
-TEST_F(TaskSchedulerWorkerPoolImplPostTaskBeforeStartTest, PostManyTasks) {
- scoped_refptr<TaskRunner> task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
- constexpr size_t kNumTasksPosted = 2 * kNumWorkersInWorkerPool;
- for (size_t i = 0; i < kNumTasksPosted; ++i)
- task_runner->PostTask(FROM_HERE, DoNothing());
-
- EXPECT_EQ(0U, worker_pool_->NumberOfWorkersForTesting());
-
- StartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool);
- ASSERT_GT(kNumTasksPosted, worker_pool_->GetWorkerCapacityForTesting());
- EXPECT_EQ(kNumWorkersInWorkerPool,
- worker_pool_->GetWorkerCapacityForTesting());
-
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(),
- worker_pool_->GetWorkerCapacityForTesting());
-}
-
-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() :
- waiter_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- void SetUp() override {
- CreateAndStartWorkerPool(kReclaimTimeForCleanupTests,
- kNumWorkersInWorkerPool);
- }
-
- 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 < kNumWorkersInWorkerPool; ++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(WrapUnique(new WaitableEvent(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED)));
- 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 pool_capacity = worker_pool_->GetWorkerCapacityForTesting();
-
- WaitableEvent workers_flooded(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure all_workers_running_barrier = BarrierClosure(
- pool_capacity,
- BindOnce(&WaitableEvent::Signal, Unretained(&workers_flooded)));
- for (size_t i = 0; i < pool_capacity; ++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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- CreateAndStartWorkerPool(TimeDelta::Max(), kNumWorkersInWorkerPool);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- CreateAndStartWorkerPool(kReclaimTimeForCleanupTests,
- kNumWorkersInWorkerPool);
-
- WaitableEvent workers_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- 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>(kNumWorkersInWorkerPool),
- histogram->SnapshotSamples()->GetCount(1));
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(10));
-
- worker_pool_->WaitForWorkersCleanedUpForTesting(kNumWorkersInWorkerPool - 1);
-
- EXPECT_EQ(0, histogram->SnapshotSamples()->GetCount(0));
- EXPECT_EQ(static_cast<int>(kNumWorkersInWorkerPool),
- 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>(kNumWorkersInWorkerPool),
- 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::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent cleanup_thread_continue(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent top_idle_thread_continue(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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));
-}
-
-TEST(TaskSchedulerWorkerPoolStandbyPolicyTest, InitOne) {
- 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);
- auto worker_pool = std::make_unique<SchedulerWorkerPoolImpl>(
- "OnePolicyWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker.GetTrackedRef(), &delayed_task_manager);
- worker_pool->Start(SchedulerWorkerPoolParams(8U, TimeDelta::Max()),
- service_thread_task_runner, nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- ASSERT_TRUE(worker_pool);
- EXPECT_EQ(1U, worker_pool->NumberOfWorkersForTesting());
- worker_pool->JoinForTesting();
-}
-
-// Verify the SchedulerWorkerPoolImpl keeps at least one idle standby thread,
-// capacity permitting.
-TEST(TaskSchedulerWorkerPoolStandbyPolicyTest, VerifyStandbyThread) {
- constexpr size_t kWorkerCapacity = 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);
- auto worker_pool = std::make_unique<SchedulerWorkerPoolImpl>(
- "StandbyThreadWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker.GetTrackedRef(), &delayed_task_manager);
- worker_pool->Start(
- SchedulerWorkerPoolParams(kWorkerCapacity, kReclaimTimeForCleanupTests),
- service_thread_task_runner, nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- ASSERT_TRUE(worker_pool);
- EXPECT_EQ(1U, worker_pool->NumberOfWorkersForTesting());
-
- auto task_runner =
- worker_pool->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent thread_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- RepeatingClosure closure = BindRepeating(
- [](WaitableEvent* thread_running, WaitableEvent* thread_continue) {
- thread_running->Signal();
- WaitWithoutBlockingObserver(thread_continue);
- },
- Unretained(&thread_running), Unretained(&thread_continue));
-
- // There should be one idle thread until we reach worker capacity
- for (size_t i = 0; i < kWorkerCapacity; ++i) {
- EXPECT_EQ(i + 1, worker_pool->NumberOfWorkersForTesting());
- task_runner->PostTask(FROM_HERE, closure);
- thread_running.Wait();
- }
-
- // There should not be an extra idle thread if it means going above capacity
- EXPECT_EQ(kWorkerCapacity, worker_pool->NumberOfWorkersForTesting());
-
- thread_continue.Signal();
- // Wait long enough for all but one worker to clean up.
- worker_pool->WaitForWorkersCleanedUpForTesting(kWorkerCapacity - 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());
-
- worker_pool->JoinForTesting();
-}
-
-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()
- : blocking_thread_running_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED),
- blocking_thread_continue_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- 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) {
- RepeatingClosure blocking_thread_running_closure =
- BarrierClosure(kNumWorkersInWorkerPool,
- BindOnce(&WaitableEvent::Signal,
- Unretained(&blocking_thread_running_)));
-
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) {
- task_runner_->PostTask(
- FROM_HERE,
- BindOnce(
- [](Closure* blocking_thread_running_closure,
- WaitableEvent* blocking_thread_continue_,
- const NestedBlockingType& nested_blocking_type) {
- NestedScopedBlockingCall nested_scoped_blocking_call(
- nested_blocking_type);
- blocking_thread_running_closure->Run();
- WaitWithoutBlockingObserver(blocking_thread_continue_);
- },
- Unretained(&blocking_thread_running_closure),
- Unretained(&blocking_thread_continue_), nested_blocking_type));
- }
- blocking_thread_running_.Wait();
- }
-
- // Returns how long we can expect a change to |worker_capacity_| to occur
- // after a task has become blocked.
- TimeDelta GetWorkerCapacityChangeSleepTime() {
- return std::max(SchedulerWorkerPoolImpl::kBlockedWorkersPollPeriod,
- worker_pool_->MayBlockThreshold()) +
- TestTimeouts::tiny_timeout();
- }
-
- // Waits indefinitely, until |worker_pool_|'s worker capacity increases to
- // |expected_worker_capacity|.
- void ExpectWorkerCapacityIncreasesTo(size_t expected_worker_capacity) {
- size_t capacity = worker_pool_->GetWorkerCapacityForTesting();
- while (capacity != expected_worker_capacity) {
- PlatformThread::Sleep(GetWorkerCapacityChangeSleepTime());
- size_t new_capacity = worker_pool_->GetWorkerCapacityForTesting();
- ASSERT_GE(new_capacity, capacity);
- capacity = new_capacity;
- }
- }
-
- // Unblocks tasks posted by SaturateWithBlockingTasks().
- void UnblockTasks() { blocking_thread_continue_.Signal(); }
-
- scoped_refptr<TaskRunner> task_runner_;
-
- private:
- WaitableEvent blocking_thread_running_;
- WaitableEvent blocking_thread_continue_;
-
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolBlockingTest);
-};
-
-// Verify that BlockingScopeEntered() causes worker capacity to increase and
-// creates a worker if needed. Also verify that BlockingScopeExited() decreases
-// worker capacity after an increase.
-TEST_P(TaskSchedulerWorkerPoolBlockingTest, ThreadBlockedUnblocked) {
- ASSERT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-
- SaturateWithBlockingTasks(GetParam());
- if (GetParam().behaves_as == BlockingType::MAY_BLOCK)
- ExpectWorkerCapacityIncreasesTo(2 * kNumWorkersInWorkerPool);
- // A range of possible number of workers is accepted because of
- // crbug.com/757897.
- EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(),
- kNumWorkersInWorkerPool + 1);
- EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(),
- 2 * kNumWorkersInWorkerPool);
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- 2 * kNumWorkersInWorkerPool);
-
- UnblockTasks();
- task_tracker_.FlushForTesting();
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-}
-
-// 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::InitialState::NOT_SIGNALED);
- WaitableEvent thread_can_block(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent thread_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) {
- task_runner_->PostTask(
- FROM_HERE,
- BindOnce(
- [](const NestedBlockingType& nested_blocking_type,
- WaitableEvent* thread_running, WaitableEvent* thread_can_block,
- WaitableEvent* thread_continue) {
- thread_running->Signal();
- WaitWithoutBlockingObserver(thread_can_block);
-
- NestedScopedBlockingCall nested_scoped_blocking_call(
- nested_blocking_type);
- WaitWithoutBlockingObserver(thread_continue);
- },
- GetParam(), Unretained(&thread_running),
- Unretained(&thread_can_block), Unretained(&thread_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(), kNumWorkersInWorkerPool);
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-
- WaitableEvent extra_thread_running(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent extra_threads_continue(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure extra_threads_running_barrier = BarrierClosure(
- kNumWorkersInWorkerPool,
- BindOnce(&WaitableEvent::Signal, Unretained(&extra_thread_running)));
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++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)
- ExpectWorkerCapacityIncreasesTo(2 * kNumWorkersInWorkerPool);
-
- // Should not block forever.
- extra_thread_running.Wait();
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(),
- 2 * kNumWorkersInWorkerPool);
- extra_threads_continue.Signal();
-
- thread_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_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-
- SaturateWithBlockingTasks(GetParam());
- if (GetParam().behaves_as == BlockingType::MAY_BLOCK)
- ExpectWorkerCapacityIncreasesTo(2 * kNumWorkersInWorkerPool);
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- 2 * kNumWorkersInWorkerPool);
- // A range of possible number of workers is accepted because of
- // crbug.com/757897.
- EXPECT_GE(worker_pool_->NumberOfWorkersForTesting(),
- kNumWorkersInWorkerPool + 1);
- EXPECT_LE(worker_pool_->NumberOfWorkersForTesting(),
- 2 * kNumWorkersInWorkerPool);
-
- WaitableEvent thread_running(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent thread_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- RepeatingClosure thread_running_barrier = BarrierClosure(
- kNumWorkersInWorkerPool,
- BindOnce(&WaitableEvent::Signal, Unretained(&thread_running)));
- // Posting these tasks should cause new workers to be created.
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) {
- auto callback = BindOnce(
- [](Closure* thread_running_barrier, WaitableEvent* thread_continue) {
- thread_running_barrier->Run();
- WaitWithoutBlockingObserver(thread_continue);
- },
- Unretained(&thread_running_barrier), Unretained(&thread_continue));
- task_runner_->PostTask(FROM_HERE, std::move(callback));
- }
- thread_running.Wait();
-
- ASSERT_EQ(worker_pool_->NumberOfIdleWorkersForTesting(), 0U);
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(),
- 2 * kNumWorkersInWorkerPool);
-
- AtomicFlag is_exiting;
- // These tasks should not get executed until after other tasks become
- // unblocked.
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++i) {
- task_runner_->PostTask(FROM_HERE, BindOnce(
- [](AtomicFlag* is_exiting) {
- EXPECT_TRUE(is_exiting->IsSet());
- },
- Unretained(&is_exiting)));
- }
-
- // The original |kNumWorkersInWorkerPool| 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(kNumWorkersInWorkerPool);
- EXPECT_EQ(worker_pool_->NumberOfIdleWorkersForTesting(),
- kNumWorkersInWorkerPool);
-
- // Posting more tasks should not cause workers idle from the pool being over
- // capacity to begin doing work.
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++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.
- thread_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
-// worker capacity does not increase.
-TEST_F(TaskSchedulerWorkerPoolBlockingTest, ThreadBlockUnblockPremature) {
- ASSERT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-
- TimeDelta worker_capacity_change_sleep = GetWorkerCapacityChangeSleepTime();
- worker_pool_->MaximizeMayBlockThresholdForTesting();
-
- SaturateWithBlockingTasks(NestedBlockingType(BlockingType::MAY_BLOCK,
- OptionalBlockingType::NO_BLOCK,
- BlockingType::MAY_BLOCK));
- PlatformThread::Sleep(worker_capacity_change_sleep);
- EXPECT_EQ(worker_pool_->NumberOfWorkersForTesting(), kNumWorkersInWorkerPool);
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-
- UnblockTasks();
- task_tracker_.FlushForTesting();
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-}
-
-// Verify that if worker capacity 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_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
- auto task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
- WaitableEvent can_return(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // Saturate the pool so that a MAY_BLOCK ScopedBlockingCall would increment
- // the worker capacity.
- for (size_t i = 0; i < kNumWorkersInWorkerPool - 1; ++i) {
- task_runner->PostTask(FROM_HERE, BindOnce(&WaitWithoutBlockingObserver,
- Unretained(&can_return)));
- }
-
- WaitableEvent can_instantiate_will_block(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent did_instantiate_will_block(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // 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, worker capacity should be incremented.
- ExpectWorkerCapacityIncreasesTo(kNumWorkersInWorkerPool + 1);
-
- // Wait until the task instantiates a WILL_BLOCK ScopedBlockingCall.
- can_instantiate_will_block.Signal();
- did_instantiate_will_block.Wait();
-
- // Worker capacity shouldn't be incremented again.
- EXPECT_EQ(kNumWorkersInWorkerPool + 1,
- worker_pool_->GetWorkerCapacityForTesting());
-
- // Tear down.
- can_return.Signal();
- task_tracker_.FlushForTesting();
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool);
-}
-
-// Verify that workers that become idle due to the pool being over capacity will
-// eventually cleanup.
-TEST(TaskSchedulerWorkerPoolOverWorkerCapacityTest, VerifyCleanup) {
- constexpr size_t kWorkerCapacity = 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(
- "OverWorkerCapacityTestWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker.GetTrackedRef(), &delayed_task_manager);
- worker_pool.Start(
- SchedulerWorkerPoolParams(kWorkerCapacity, kReclaimTimeForCleanupTests),
- service_thread_task_runner, nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
-
- scoped_refptr<TaskRunner> task_runner =
- worker_pool.CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent threads_running(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent threads_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure threads_running_barrier = BarrierClosure(
- kWorkerCapacity,
- BindOnce(&WaitableEvent::Signal, Unretained(&threads_running)));
-
- WaitableEvent blocked_call_continue(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- 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 < kWorkerCapacity; ++i)
- task_runner->PostTask(FROM_HERE, closure);
-
- threads_running.Wait();
-
- WaitableEvent extra_threads_running(
- WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent extra_threads_continue(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- RepeatingClosure extra_threads_running_barrier = BarrierClosure(
- kWorkerCapacity,
- BindOnce(&WaitableEvent::Signal, Unretained(&extra_threads_running)));
- // These tasks should run on the new threads from increasing worker capacity.
- for (size_t i = 0; i < kWorkerCapacity; ++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(kWorkerCapacity * 2, worker_pool.NumberOfWorkersForTesting());
- EXPECT_EQ(kWorkerCapacity * 2, worker_pool.GetWorkerCapacityForTesting());
- 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(kWorkerCapacity - 1);
- EXPECT_EQ(kWorkerCapacity + 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 worker capacity.
-TEST_F(TaskSchedulerWorkerPoolBlockingTest, MaximumWorkersTest) {
- constexpr size_t kMaxNumberOfWorkers = 256;
- constexpr size_t kNumExtraTasks = 10;
-
- WaitableEvent early_blocking_thread_running(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure early_threads_barrier_closure =
- BarrierClosure(kMaxNumberOfWorkers,
- BindOnce(&WaitableEvent::Signal,
- Unretained(&early_blocking_thread_running)));
-
- WaitableEvent early_threads_finished(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure early_threads_finished_barrier = BarrierClosure(
- kMaxNumberOfWorkers,
- BindOnce(&WaitableEvent::Signal, Unretained(&early_threads_finished)));
-
- WaitableEvent early_release_thread_continue(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- // 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_thread_continue,
- Closure* early_threads_finished) {
- {
- ScopedBlockingCall scoped_blocking_call(
- BlockingType::WILL_BLOCK);
- early_threads_barrier_closure->Run();
- WaitWithoutBlockingObserver(
- early_release_thread_continue);
- }
- early_threads_finished->Run();
- },
- Unretained(&early_threads_barrier_closure),
- Unretained(&early_release_thread_continue),
- Unretained(&early_threads_finished_barrier)));
- }
-
- early_blocking_thread_running.Wait();
- EXPECT_EQ(worker_pool_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool + kMaxNumberOfWorkers);
-
- WaitableEvent late_release_thread_contine(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitableEvent late_blocking_thread_running(
- WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure late_threads_barrier_closure = BarrierClosure(
- kNumExtraTasks, BindOnce(&WaitableEvent::Signal,
- Unretained(&late_blocking_thread_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_thread_continue.Signal();
- early_threads_finished.Wait();
- late_blocking_thread_running.Wait();
-
- WaitableEvent final_tasks_running(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent final_tasks_continue(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure final_tasks_running_barrier = BarrierClosure(
- kNumWorkersInWorkerPool,
- BindOnce(&WaitableEvent::Signal, Unretained(&final_tasks_running)));
-
- // Verify that we are still able to saturate the pool.
- for (size_t i = 0; i < kNumWorkersInWorkerPool; ++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_->GetWorkerCapacityForTesting(),
- kNumWorkersInWorkerPool + kNumExtraTasks);
- late_release_thread_contine.Signal();
- final_tasks_continue.Signal();
- task_tracker_.FlushForTesting();
-}
-
-// Verify that worker detachement doesn't race with worker cleanup, regression
-// test for https://crbug.com/810464.
-TEST(TaskSchedulerWorkerPoolTest, 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 kWorkerCapacity = 16;
-#else // defined(OS_FUCHSIA)
- constexpr size_t kWorkerCapacity = 256;
-#endif // defined(OS_FUCHSIA)
- constexpr TimeDelta kReclaimTimeForRacyCleanupTest =
- TimeDelta::FromMilliseconds(10);
-
- 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(
- "RacyCleanupTestWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker.GetTrackedRef(), &delayed_task_manager);
- worker_pool.Start(SchedulerWorkerPoolParams(kWorkerCapacity,
- kReclaimTimeForRacyCleanupTest),
- service_thread_task_runner, nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
-
- scoped_refptr<TaskRunner> task_runner =
- worker_pool.CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- WaitableEvent threads_running(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent unblock_threads(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingClosure threads_running_barrier = BarrierClosure(
- kWorkerCapacity,
- BindOnce(&WaitableEvent::Signal, Unretained(&threads_running)));
-
- for (size_t i = 0; i < kWorkerCapacity; ++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.
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/scheduler_worker_pool_unittest.cc b/base/task_scheduler/scheduler_worker_pool_unittest.cc
deleted file mode 100644
index 20c1ad0..0000000
--- a/base/task_scheduler/scheduler_worker_pool_unittest.cc
+++ /dev/null
@@ -1,345 +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_worker_pool.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/location.h"
-#include "base/memory/ref_counted.h"
-#include "base/task_runner.h"
-#include "base/task_scheduler/delayed_task_manager.h"
-#include "base/task_scheduler/scheduler_worker_pool_impl.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/task_scheduler/test_task_factory.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/threading/thread.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-#include "base/task_scheduler/platform_native_worker_pool_win.h"
-#endif
-
-namespace base {
-namespace internal {
-
-namespace {
-
-constexpr size_t kNumWorkersInWorkerPool = 4;
-constexpr size_t kNumThreadsPostingTasks = 4;
-constexpr size_t kNumTasksPostedPerThread = 150;
-
-enum class PoolType {
- GENERIC,
-#if defined(OS_WIN)
- WINDOWS,
-#endif
-};
-
-struct PoolExecutionType {
- PoolType pool_type;
- test::ExecutionMode execution_mode;
-};
-
-using PostNestedTask = test::TestTaskFactory::PostNestedTask;
-
-class ThreadPostingTasks : public SimpleThread {
- public:
- // Constructs a thread that posts |num_tasks_posted_per_thread| tasks to
- // |worker_pool| through an |execution_mode| task runner. If
- // |post_nested_task| is YES, each task posted by this thread posts another
- // task when it runs.
- ThreadPostingTasks(SchedulerWorkerPool* worker_pool,
- test::ExecutionMode execution_mode,
- PostNestedTask post_nested_task)
- : SimpleThread("ThreadPostingTasks"),
- worker_pool_(worker_pool),
- post_nested_task_(post_nested_task),
- factory_(test::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)
- EXPECT_TRUE(factory_.PostTask(post_nested_task_, Closure()));
- }
-
- SchedulerWorkerPool* const worker_pool_;
- const scoped_refptr<TaskRunner> task_runner_;
- const PostNestedTask post_nested_task_;
- test::TestTaskFactory factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPostingTasks);
-};
-
-class TaskSchedulerWorkerPoolTest
- : public testing::TestWithParam<PoolExecutionType> {
- protected:
- TaskSchedulerWorkerPoolTest()
- : service_thread_("TaskSchedulerServiceThread") {}
-
- void SetUp() override {
- service_thread_.Start();
- delayed_task_manager_.Start(service_thread_.task_runner());
- CreateWorkerPool();
- }
-
- void TearDown() override {
- service_thread_.Stop();
- if (worker_pool_)
- worker_pool_->JoinForTesting();
- }
-
- void CreateWorkerPool() {
- ASSERT_FALSE(worker_pool_);
- switch (GetParam().pool_type) {
- case PoolType::GENERIC:
- worker_pool_ = std::make_unique<SchedulerWorkerPoolImpl>(
- "TestWorkerPool", "A", ThreadPriority::NORMAL,
- task_tracker_.GetTrackedRef(), &delayed_task_manager_);
- break;
-#if defined(OS_WIN)
- case PoolType::WINDOWS:
- worker_pool_ = std::make_unique<PlatformNativeWorkerPoolWin>(
- task_tracker_.GetTrackedRef(), &delayed_task_manager_);
- break;
-#endif
- }
- ASSERT_TRUE(worker_pool_);
- }
-
- void StartWorkerPool() {
- ASSERT_TRUE(worker_pool_);
- switch (GetParam().pool_type) {
- case PoolType::GENERIC: {
- SchedulerWorkerPoolImpl* scheduler_worker_pool_impl =
- static_cast<SchedulerWorkerPoolImpl*>(worker_pool_.get());
- scheduler_worker_pool_impl->Start(
- SchedulerWorkerPoolParams(kNumWorkersInWorkerPool,
- TimeDelta::Max()),
- service_thread_.task_runner(), nullptr,
- SchedulerWorkerPoolImpl::WorkerEnvironment::NONE);
- break;
- }
-#if defined(OS_WIN)
- case PoolType::WINDOWS: {
- PlatformNativeWorkerPoolWin* scheduler_worker_pool_windows_impl =
- static_cast<PlatformNativeWorkerPoolWin*>(worker_pool_.get());
- scheduler_worker_pool_windows_impl->Start();
- break;
- }
-#endif
- }
- }
-
- Thread service_thread_;
- TaskTracker task_tracker_ = {"Test"};
- DelayedTaskManager delayed_task_manager_;
-
- std::unique_ptr<SchedulerWorkerPool> worker_pool_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TaskSchedulerWorkerPoolTest);
-};
-
-void ShouldNotRun() {
- ADD_FAILURE() << "Ran a task that shouldn't run.";
-}
-
-} // namespace
-
-TEST_P(TaskSchedulerWorkerPoolTest, PostTasks) {
- StartWorkerPool();
- // Create threads to post tasks.
- std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
- for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) {
- threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
- worker_pool_.get(), GetParam().execution_mode, PostNestedTask::NO));
- 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();
- }
-
- // Flush the task tracker to be sure that no task accesses its TestTaskFactory
- // after |thread_posting_tasks| is destroyed.
- task_tracker_.FlushForTesting();
-}
-
-TEST_P(TaskSchedulerWorkerPoolTest, NestedPostTasks) {
- StartWorkerPool();
- // Create threads to post tasks. Each task posted by these threads will post
- // another task when it runs.
- std::vector<std::unique_ptr<ThreadPostingTasks>> threads_posting_tasks;
- for (size_t i = 0; i < kNumThreadsPostingTasks; ++i) {
- threads_posting_tasks.push_back(std::make_unique<ThreadPostingTasks>(
- worker_pool_.get(), GetParam().execution_mode, PostNestedTask::YES));
- 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();
- }
-
- // Flush the task tracker to be sure that no task accesses its TestTaskFactory
- // after |thread_posting_tasks| is destroyed.
- task_tracker_.FlushForTesting();
-}
-
-// Verify that a Task can't be posted after shutdown.
-TEST_P(TaskSchedulerWorkerPoolTest, PostTaskAfterShutdown) {
- StartWorkerPool();
- auto task_runner = test::CreateTaskRunnerWithExecutionMode(
- worker_pool_.get(), GetParam().execution_mode);
- task_tracker_.Shutdown();
- EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
-}
-
-// Verify that posting tasks after the pool was destroyed fails but doesn't
-// crash.
-TEST_P(TaskSchedulerWorkerPoolTest, PostAfterDestroy) {
- StartWorkerPool();
- auto task_runner = test::CreateTaskRunnerWithExecutionMode(
- worker_pool_.get(), GetParam().execution_mode);
- EXPECT_TRUE(task_runner->PostTask(FROM_HERE, DoNothing()));
- task_tracker_.Shutdown();
- worker_pool_->JoinForTesting();
- worker_pool_.reset();
- EXPECT_FALSE(task_runner->PostTask(FROM_HERE, BindOnce(&ShouldNotRun)));
-}
-
-// Verify that a Task runs shortly after its delay expires.
-TEST_P(TaskSchedulerWorkerPoolTest, PostDelayedTask) {
- StartWorkerPool();
-
- WaitableEvent task_ran(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- auto task_runner = test::CreateTaskRunnerWithExecutionMode(
- worker_pool_.get(), GetParam().execution_mode);
-
- // 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.
- TimeTicks start_time = TimeTicks::Now();
- 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 the RunsTasksInCurrentSequence() method of a SEQUENCED TaskRunner
-// returns false when called from a task that isn't part of the sequence. Note:
-// Tests that use TestTaskFactory already verify that
-// RunsTasksInCurrentSequence() returns true when appropriate so this method
-// complements it to get full coverage of that method.
-TEST_P(TaskSchedulerWorkerPoolTest, SequencedRunsTasksInCurrentSequence) {
- StartWorkerPool();
- auto task_runner = test::CreateTaskRunnerWithExecutionMode(
- worker_pool_.get(), GetParam().execution_mode);
- auto sequenced_task_runner =
- worker_pool_->CreateSequencedTaskRunnerWithTraits(TaskTraits());
-
- WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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 tasks posted before Start run after Start.
-TEST_P(TaskSchedulerWorkerPoolTest, PostBeforeStart) {
- WaitableEvent task_1_running(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent task_2_running(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- scoped_refptr<TaskRunner> task_runner =
- worker_pool_->CreateTaskRunnerWithTraits({WithBaseSyncPrimitives()});
-
- task_runner->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_1_running)));
- task_runner->PostTask(
- FROM_HERE, BindOnce(&WaitableEvent::Signal, Unretained(&task_2_running)));
-
- // Workers should not be created and tasks should not run before the pool is
- // started. The sleep is to give time for the tasks to potentially run.
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- EXPECT_FALSE(task_1_running.IsSignaled());
- EXPECT_FALSE(task_2_running.IsSignaled());
-
- StartWorkerPool();
-
- // Tasks should run shortly after the pool is started.
- task_1_running.Wait();
- task_2_running.Wait();
-
- task_tracker_.FlushForTesting();
-}
-
-INSTANTIATE_TEST_CASE_P(GenericParallel,
- TaskSchedulerWorkerPoolTest,
- ::testing::Values(PoolExecutionType{
- PoolType::GENERIC, test::ExecutionMode::PARALLEL}));
-INSTANTIATE_TEST_CASE_P(GenericSequenced,
- TaskSchedulerWorkerPoolTest,
- ::testing::Values(PoolExecutionType{
- PoolType::GENERIC,
- test::ExecutionMode::SEQUENCED}));
-
-#if defined(OS_WIN)
-INSTANTIATE_TEST_CASE_P(WinParallel,
- TaskSchedulerWorkerPoolTest,
- ::testing::Values(PoolExecutionType{
- PoolType::WINDOWS, test::ExecutionMode::PARALLEL}));
-INSTANTIATE_TEST_CASE_P(WinSequenced,
- TaskSchedulerWorkerPoolTest,
- ::testing::Values(PoolExecutionType{
- PoolType::WINDOWS,
- test::ExecutionMode::SEQUENCED}));
-#endif
-
-} // 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 8707874..0000000
--- a/base/task_scheduler/scheduler_worker_stack_unittest.cc
+++ /dev/null
@@ -1,253 +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());
- EXPECT_TRUE(stack.IsEmpty());
-
- stack.Push(worker_a_.get());
- EXPECT_EQ(1U, stack.Size());
- EXPECT_FALSE(stack.IsEmpty());
-
- stack.Remove(worker_a_.get());
- EXPECT_EQ(0U, stack.Size());
- EXPECT_TRUE(stack.IsEmpty());
-
- stack.Push(worker_a_.get());
- EXPECT_EQ(1U, stack.Size());
- EXPECT_FALSE(stack.IsEmpty());
-}
-
-// 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 b7a2eda..0000000
--- a/base/task_scheduler/scheduler_worker_unittest.cc
+++ /dev/null
@@ -1,907 +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/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_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()
- : main_entry_called_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- num_get_work_cv_(lock_.CreateConditionVariable()),
- worker_set_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- 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()
- : work_running_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::SIGNALED),
- work_processed_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- cleanup_requested_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- destroyed_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- exited_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- 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 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),
- run_started_event_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- ~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) {
- TaskTracker task_tracker("Test");
-
- std::unique_ptr<ExpectThreadPriorityDelegate> delegate(
- new ExpectThreadPriorityDelegate);
- ExpectThreadPriorityDelegate* delegate_raw = delegate.get();
- delegate_raw->SetExpectedThreadPriority(
- PlatformThread::CanIncreaseCurrentThreadPriority()
- ? ThreadPriority::BACKGROUND
- : ThreadPriority::NORMAL);
-
- 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
-
-// Verify that the SchedulerWorkerObserver is notified when the worker enters
-// and exits its main function.
-TEST(TaskSchedulerWorkerTest, 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()
- : get_work_returned_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- 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/scoped_set_task_priority_for_current_thread_unittest.cc b/base/task_scheduler/scoped_set_task_priority_for_current_thread_unittest.cc
deleted file mode 100644
index c497af6..0000000
--- a/base/task_scheduler/scoped_set_task_priority_for_current_thread_unittest.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/task_scheduler/scoped_set_task_priority_for_current_thread.h"
-
-#include "base/task_scheduler/task_traits.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-TEST(TaskSchedulerScopedSetTaskPriorityForCurrentThreadTest,
- ScopedSetTaskPriorityForCurrentThread) {
- EXPECT_EQ(TaskPriority::USER_VISIBLE, GetTaskPriorityForCurrentThread());
- {
- ScopedSetTaskPriorityForCurrentThread
- scoped_set_task_priority_for_current_thread(
- TaskPriority::USER_BLOCKING);
- EXPECT_EQ(TaskPriority::USER_BLOCKING, GetTaskPriorityForCurrentThread());
- }
- EXPECT_EQ(TaskPriority::USER_VISIBLE, GetTaskPriorityForCurrentThread());
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/sequence_sort_key_unittest.cc b/base/task_scheduler/sequence_sort_key_unittest.cc
deleted file mode 100644
index 2c1d80d..0000000
--- a/base/task_scheduler/sequence_sort_key_unittest.cc
+++ /dev/null
@@ -1,243 +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/sequence_sort_key.h"
-
-#include "base/task_scheduler/task_traits.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-TEST(TaskSchedulerSequenceSortKeyTest, OperatorLessThan) {
- SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_c(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_d(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_e(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_f(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(2000));
-
- EXPECT_FALSE(key_a < key_a);
- EXPECT_LT(key_b, key_a);
- EXPECT_LT(key_c, key_a);
- EXPECT_LT(key_d, key_a);
- EXPECT_LT(key_e, key_a);
- EXPECT_LT(key_f, key_a);
-
- EXPECT_FALSE(key_a < key_b);
- EXPECT_FALSE(key_b < key_b);
- EXPECT_LT(key_c, key_b);
- EXPECT_LT(key_d, key_b);
- EXPECT_LT(key_e, key_b);
- EXPECT_LT(key_f, key_b);
-
- EXPECT_FALSE(key_a < key_c);
- EXPECT_FALSE(key_b < key_c);
- EXPECT_FALSE(key_c < key_c);
- EXPECT_LT(key_d, key_c);
- EXPECT_LT(key_e, key_c);
- EXPECT_LT(key_f, key_c);
-
- EXPECT_FALSE(key_a < key_d);
- EXPECT_FALSE(key_b < key_d);
- EXPECT_FALSE(key_c < key_d);
- EXPECT_FALSE(key_d < key_d);
- EXPECT_LT(key_e, key_d);
- EXPECT_LT(key_f, key_d);
-
- EXPECT_FALSE(key_a < key_e);
- EXPECT_FALSE(key_b < key_e);
- EXPECT_FALSE(key_c < key_e);
- EXPECT_FALSE(key_d < key_e);
- EXPECT_FALSE(key_e < key_e);
- EXPECT_LT(key_f, key_e);
-
- EXPECT_FALSE(key_a < key_f);
- EXPECT_FALSE(key_b < key_f);
- EXPECT_FALSE(key_c < key_f);
- EXPECT_FALSE(key_d < key_f);
- EXPECT_FALSE(key_e < key_f);
- EXPECT_FALSE(key_f < key_f);
-}
-
-TEST(TaskSchedulerSequenceSortKeyTest, OperatorGreaterThan) {
- SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_c(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_d(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_e(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_f(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(2000));
-
- EXPECT_FALSE(key_a > key_a);
- EXPECT_FALSE(key_b > key_a);
- EXPECT_FALSE(key_c > key_a);
- EXPECT_FALSE(key_d > key_a);
- EXPECT_FALSE(key_e > key_a);
- EXPECT_FALSE(key_f > key_a);
-
- EXPECT_GT(key_a, key_b);
- EXPECT_FALSE(key_b > key_b);
- EXPECT_FALSE(key_c > key_b);
- EXPECT_FALSE(key_d > key_b);
- EXPECT_FALSE(key_e > key_b);
- EXPECT_FALSE(key_f > key_b);
-
- EXPECT_GT(key_a, key_c);
- EXPECT_GT(key_b, key_c);
- EXPECT_FALSE(key_c > key_c);
- EXPECT_FALSE(key_d > key_c);
- EXPECT_FALSE(key_e > key_c);
- EXPECT_FALSE(key_f > key_c);
-
- EXPECT_GT(key_a, key_d);
- EXPECT_GT(key_b, key_d);
- EXPECT_GT(key_c, key_d);
- EXPECT_FALSE(key_d > key_d);
- EXPECT_FALSE(key_e > key_d);
- EXPECT_FALSE(key_f > key_d);
-
- EXPECT_GT(key_a, key_e);
- EXPECT_GT(key_b, key_e);
- EXPECT_GT(key_c, key_e);
- EXPECT_GT(key_d, key_e);
- EXPECT_FALSE(key_e > key_e);
- EXPECT_FALSE(key_f > key_e);
-
- EXPECT_GT(key_a, key_f);
- EXPECT_GT(key_b, key_f);
- EXPECT_GT(key_c, key_f);
- EXPECT_GT(key_d, key_f);
- EXPECT_GT(key_e, key_f);
- EXPECT_FALSE(key_f > key_f);
-}
-
-TEST(TaskSchedulerSequenceSortKeyTest, OperatorEqual) {
- SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_c(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_d(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_e(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_f(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(2000));
-
- EXPECT_EQ(key_a, key_a);
- EXPECT_FALSE(key_b == key_a);
- EXPECT_FALSE(key_c == key_a);
- EXPECT_FALSE(key_d == key_a);
- EXPECT_FALSE(key_e == key_a);
- EXPECT_FALSE(key_f == key_a);
-
- EXPECT_FALSE(key_a == key_b);
- EXPECT_EQ(key_b, key_b);
- EXPECT_FALSE(key_c == key_b);
- EXPECT_FALSE(key_d == key_b);
- EXPECT_FALSE(key_e == key_b);
- EXPECT_FALSE(key_f == key_b);
-
- EXPECT_FALSE(key_a == key_c);
- EXPECT_FALSE(key_b == key_c);
- EXPECT_EQ(key_c, key_c);
- EXPECT_FALSE(key_d == key_c);
- EXPECT_FALSE(key_e == key_c);
- EXPECT_FALSE(key_f == key_c);
-
- EXPECT_FALSE(key_a == key_d);
- EXPECT_FALSE(key_b == key_d);
- EXPECT_FALSE(key_c == key_d);
- EXPECT_EQ(key_d, key_d);
- EXPECT_FALSE(key_e == key_d);
- EXPECT_FALSE(key_f == key_d);
-
- EXPECT_FALSE(key_a == key_e);
- EXPECT_FALSE(key_b == key_e);
- EXPECT_FALSE(key_c == key_e);
- EXPECT_FALSE(key_d == key_e);
- EXPECT_EQ(key_e, key_e);
- EXPECT_FALSE(key_f == key_e);
-
- EXPECT_FALSE(key_a == key_f);
- EXPECT_FALSE(key_b == key_f);
- EXPECT_FALSE(key_c == key_f);
- EXPECT_FALSE(key_d == key_f);
- EXPECT_FALSE(key_e == key_f);
- EXPECT_EQ(key_f, key_f);
-}
-
-TEST(TaskSchedulerSequenceSortKeyTest, OperatorNotEqual) {
- SequenceSortKey key_a(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_b(TaskPriority::USER_BLOCKING,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_c(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_d(TaskPriority::USER_VISIBLE,
- TimeTicks::FromInternalValue(2000));
- SequenceSortKey key_e(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(1000));
- SequenceSortKey key_f(TaskPriority::BACKGROUND,
- TimeTicks::FromInternalValue(2000));
-
- EXPECT_FALSE(key_a != key_a);
- EXPECT_NE(key_b, key_a);
- EXPECT_NE(key_c, key_a);
- EXPECT_NE(key_d, key_a);
- EXPECT_NE(key_e, key_a);
- EXPECT_NE(key_f, key_a);
-
- EXPECT_NE(key_a, key_b);
- EXPECT_FALSE(key_b != key_b);
- EXPECT_NE(key_c, key_b);
- EXPECT_NE(key_d, key_b);
- EXPECT_NE(key_e, key_b);
- EXPECT_NE(key_f, key_b);
-
- EXPECT_NE(key_a, key_c);
- EXPECT_NE(key_b, key_c);
- EXPECT_FALSE(key_c != key_c);
- EXPECT_NE(key_d, key_c);
- EXPECT_NE(key_e, key_c);
- EXPECT_NE(key_f, key_c);
-
- EXPECT_NE(key_a, key_d);
- EXPECT_NE(key_b, key_d);
- EXPECT_NE(key_c, key_d);
- EXPECT_FALSE(key_d != key_d);
- EXPECT_NE(key_e, key_d);
- EXPECT_NE(key_f, key_d);
-
- EXPECT_NE(key_a, key_e);
- EXPECT_NE(key_b, key_e);
- EXPECT_NE(key_c, key_e);
- EXPECT_NE(key_d, key_e);
- EXPECT_FALSE(key_e != key_e);
- EXPECT_NE(key_f, key_e);
-
- EXPECT_NE(key_a, key_f);
- EXPECT_NE(key_b, key_f);
- EXPECT_NE(key_c, key_f);
- EXPECT_NE(key_d, key_f);
- EXPECT_NE(key_e, key_f);
- EXPECT_FALSE(key_f != key_f);
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/sequence_unittest.cc b/base/task_scheduler/sequence_unittest.cc
deleted file mode 100644
index 86d1547..0000000
--- a/base/task_scheduler/sequence_unittest.cc
+++ /dev/null
@@ -1,172 +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/sequence.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/memory/ptr_util.h"
-#include "base/test/gtest_util.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 {
-
-class MockTask {
- public:
- MOCK_METHOD0(Run, void());
-};
-
-Task CreateTask(MockTask* mock_task) {
- return Task(FROM_HERE, BindOnce(&MockTask::Run, Unretained(mock_task)),
- {TaskPriority::BACKGROUND}, TimeDelta());
-}
-
-void ExpectMockTask(MockTask* mock_task, Task* task) {
- EXPECT_CALL(*mock_task, Run());
- std::move(task->task).Run();
- testing::Mock::VerifyAndClear(mock_task);
-}
-
-} // namespace
-
-TEST(TaskSchedulerSequenceTest, PushTakeRemove) {
- testing::StrictMock<MockTask> mock_task_a;
- testing::StrictMock<MockTask> mock_task_b;
- testing::StrictMock<MockTask> mock_task_c;
- testing::StrictMock<MockTask> mock_task_d;
- testing::StrictMock<MockTask> mock_task_e;
-
- scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
-
- // Push task A in the sequence. PushTask() should return true since it's the
- // first task->
- EXPECT_TRUE(sequence->PushTask(CreateTask(&mock_task_a)));
-
- // Push task B, C and D in the sequence. PushTask() should return false since
- // there is already a task in a sequence.
- EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_b)));
- EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_c)));
- EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_d)));
-
- // Take the task in front of the sequence. It should be task A.
- Optional<Task> task = sequence->TakeTask();
- ExpectMockTask(&mock_task_a, &task.value());
- EXPECT_FALSE(task->sequenced_time.is_null());
-
- // Remove the empty slot. Task B should now be in front.
- EXPECT_FALSE(sequence->Pop());
- task = sequence->TakeTask();
- ExpectMockTask(&mock_task_b, &task.value());
- EXPECT_FALSE(task->sequenced_time.is_null());
-
- // Remove the empty slot. Task C should now be in front.
- EXPECT_FALSE(sequence->Pop());
- task = sequence->TakeTask();
- ExpectMockTask(&mock_task_c, &task.value());
- EXPECT_FALSE(task->sequenced_time.is_null());
-
- // Remove the empty slot.
- EXPECT_FALSE(sequence->Pop());
-
- // Push task E in the sequence.
- EXPECT_FALSE(sequence->PushTask(CreateTask(&mock_task_e)));
-
- // Task D should be in front.
- task = sequence->TakeTask();
- ExpectMockTask(&mock_task_d, &task.value());
- EXPECT_FALSE(task->sequenced_time.is_null());
-
- // Remove the empty slot. Task E should now be in front.
- EXPECT_FALSE(sequence->Pop());
- task = sequence->TakeTask();
- ExpectMockTask(&mock_task_e, &task.value());
- EXPECT_FALSE(task->sequenced_time.is_null());
-
- // Remove the empty slot. The sequence should now be empty.
- EXPECT_TRUE(sequence->Pop());
-}
-
-// Verifies the sort key of a sequence that contains one BACKGROUND task.
-TEST(TaskSchedulerSequenceTest, GetSortKeyBackground) {
- // Create a sequence with a BACKGROUND task.
- Task background_task(FROM_HERE, DoNothing(), {TaskPriority::BACKGROUND},
- TimeDelta());
- scoped_refptr<Sequence> background_sequence = MakeRefCounted<Sequence>();
- background_sequence->PushTask(std::move(background_task));
-
- // Get the sort key.
- const SequenceSortKey background_sort_key = background_sequence->GetSortKey();
-
- // Take the task from the sequence, so that its sequenced time is available
- // for the check below.
- auto take_background_task = background_sequence->TakeTask();
-
- // Verify the sort key.
- EXPECT_EQ(TaskPriority::BACKGROUND, background_sort_key.priority());
- EXPECT_EQ(take_background_task->sequenced_time,
- background_sort_key.next_task_sequenced_time());
-
- // Pop for correctness.
- background_sequence->Pop();
-}
-
-// Same as TaskSchedulerSequenceTest.GetSortKeyBackground, but with a
-// USER_VISIBLE task.
-TEST(TaskSchedulerSequenceTest, GetSortKeyForeground) {
- // Create a sequence with a USER_VISIBLE task.
- Task foreground_task(FROM_HERE, DoNothing(), {TaskPriority::USER_VISIBLE},
- TimeDelta());
- scoped_refptr<Sequence> foreground_sequence = MakeRefCounted<Sequence>();
- foreground_sequence->PushTask(std::move(foreground_task));
-
- // Get the sort key.
- const SequenceSortKey foreground_sort_key = foreground_sequence->GetSortKey();
-
- // Take the task from the sequence, so that its sequenced time is available
- // for the check below.
- auto take_foreground_task = foreground_sequence->TakeTask();
-
- // Verify the sort key.
- EXPECT_EQ(TaskPriority::USER_VISIBLE, foreground_sort_key.priority());
- EXPECT_EQ(take_foreground_task->sequenced_time,
- foreground_sort_key.next_task_sequenced_time());
-
- // Pop for correctness.
- foreground_sequence->Pop();
-}
-
-// Verify that a DCHECK fires if Pop() is called on a sequence whose front slot
-// isn't empty.
-TEST(TaskSchedulerSequenceTest, PopNonEmptyFrontSlot) {
- scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
- sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()));
-
- EXPECT_DCHECK_DEATH({ sequence->Pop(); });
-}
-
-// Verify that a DCHECK fires if TakeTask() is called on a sequence whose front
-// slot is empty.
-TEST(TaskSchedulerSequenceTest, TakeEmptyFrontSlot) {
- scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
- sequence->PushTask(Task(FROM_HERE, DoNothing(), TaskTraits(), TimeDelta()));
-
- EXPECT_TRUE(sequence->TakeTask());
- EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
-}
-
-// Verify that a DCHECK fires if TakeTask() is called on an empty sequence.
-TEST(TaskSchedulerSequenceTest, TakeEmptySequence) {
- scoped_refptr<Sequence> sequence = MakeRefCounted<Sequence>();
- EXPECT_DCHECK_DEATH({ sequence->TakeTask(); });
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/task_scheduler/service_thread_unittest.cc b/base/task_scheduler/service_thread_unittest.cc
deleted file mode 100644
index df4d8d6..0000000
--- a/base/task_scheduler/service_thread_unittest.cc
+++ /dev/null
@@ -1,96 +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/task_scheduler/service_thread.h"
-
-#include <string>
-
-#include "base/bind.h"
-#include "base/debug/stack_trace.h"
-#include "base/task_scheduler/task_scheduler.h"
-#include "base/task_scheduler/task_scheduler_impl.h"
-#include "base/test/histogram_tester.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-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_StackHasIdentifyingFrame DISABLED_StackHasIdentifyingFrame
-#else
-#define MAYBE_StackHasIdentifyingFrame StackHasIdentifyingFrame
-#endif
-
-TEST(TaskSchedulerServiceThreadTest, MAYBE_StackHasIdentifyingFrame) {
- ServiceThread service_thread(nullptr);
- service_thread.Start();
-
- service_thread.task_runner()->PostTask(
- FROM_HERE, BindOnce(&VerifyHasStringOnStack, "ServiceThread"));
-
- service_thread.FlushForTesting();
-}
-
-// Integration test verifying that a service thread running in a fully
-// integrated TaskScheduler environment results in reporting
-// HeartbeatLatencyMicroseconds metrics.
-TEST(TaskSchedulerServiceThreadIntegrationTest, HeartbeatLatencyReport) {
- TaskScheduler::SetInstance(
- std::make_unique<internal::TaskSchedulerImpl>("Test"));
- TaskScheduler::GetInstance()->StartWithDefaultParams();
-
- static constexpr const char* kExpectedMetrics[] = {
- "TaskScheduler.HeartbeatLatencyMicroseconds.Test."
- "UserBlockingTaskPriority",
- "TaskScheduler.HeartbeatLatencyMicroseconds.Test."
- "UserBlockingTaskPriority_MayBlock",
- "TaskScheduler.HeartbeatLatencyMicroseconds.Test."
- "UserVisibleTaskPriority",
- "TaskScheduler.HeartbeatLatencyMicroseconds.Test."
- "UserVisibleTaskPriority_MayBlock",
- "TaskScheduler.HeartbeatLatencyMicroseconds.Test."
- "BackgroundTaskPriority",
- "TaskScheduler.HeartbeatLatencyMicroseconds.Test."
- "BackgroundTaskPriority_MayBlock"};
-
- constexpr TimeDelta kReasonableTimeout = TimeDelta::FromSeconds(6);
- constexpr TimeDelta kBusyWaitTime = TimeDelta::FromMilliseconds(100);
-
- const TimeTicks start_time = TimeTicks::Now();
-
- HistogramTester tester;
- for (const char* expected_metric : kExpectedMetrics) {
- for (int i = 0; tester.GetAllSamples(expected_metric).empty(); ++i) {
- if (TimeTicks::Now() - start_time > kReasonableTimeout)
- LOG(WARNING) << "Waiting a while for " << expected_metric;
- PlatformThread::Sleep(kBusyWaitTime);
- }
- }
-
- TaskScheduler::GetInstance()->JoinForTesting();
- TaskScheduler::SetInstance(nullptr);
-}
-
-} // 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 6eee033..0000000
--- a/base/task_scheduler/task_scheduler_impl_unittest.cc
+++ /dev/null
@@ -1,823 +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/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/lock.h"
-#include "base/synchronization/waitable_event.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/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_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) {
- const bool supports_background_priority =
- Lock::HandlesMultipleThreadPriorities() &&
- PlatformThread::CanIncreaseCurrentThreadPriority();
-
- EXPECT_EQ(supports_background_priority &&
- 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"));
- EXPECT_NE(std::string::npos,
- current_thread_name.find(
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- // 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- CreateTaskRunnerWithTraitsAndExecutionMode(
- &scheduler_,
- TaskTraits::Override(GetParam().traits, {WithBaseSyncPrimitives()}),
- GetParam().execution_mode, SingleThreadTaskRunnerThreadMode::DEDICATED)
- ->PostTask(FROM_HERE,
- BindOnce(&WaitableEvent::Wait, Unretained(&unblock_task)));
-
- WaitableEvent flush_event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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();
- EXPECT_EQ(1, scheduler_.GetMaxConcurrentNonBlockedTasksWithTraitsDeprecated(
- {TaskPriority::BACKGROUND}));
- EXPECT_EQ(3, 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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
-#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);
-
-// 4 workers should be created for the 4 pools. After that, 8 threads should
-// be created for single-threaded work (16 on Windows).
-#if defined(OS_WIN)
- constexpr int kExpectedNumWorkers = 20;
-#else
- constexpr int kExpectedNumWorkers = 12;
-#endif
- 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 d8849de..0000000
--- 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 ea8a3c1..0000000
--- a/base/task_scheduler/task_tracker_unittest.cc
+++ /dev/null
@@ -1,1368 +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/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) {
- const 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) {
- const 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- 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_traits_unittest.cc b/base/task_scheduler/task_traits_unittest.cc
deleted file mode 100644
index 2a35048..0000000
--- a/base/task_scheduler/task_traits_unittest.cc
+++ /dev/null
@@ -1,175 +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/task_traits.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(TaskSchedulerTaskTraitsTest, Default) {
- constexpr TaskTraits traits = {};
- EXPECT_FALSE(traits.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, traits.priority());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
- EXPECT_FALSE(traits.may_block());
- EXPECT_FALSE(traits.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, TaskPriority) {
- constexpr TaskTraits traits = {TaskPriority::BACKGROUND};
- EXPECT_TRUE(traits.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::BACKGROUND, traits.priority());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
- EXPECT_FALSE(traits.may_block());
- EXPECT_FALSE(traits.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, TaskShutdownBehavior) {
- constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN};
- EXPECT_FALSE(traits.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, traits.priority());
- EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior());
- EXPECT_FALSE(traits.may_block());
- EXPECT_FALSE(traits.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, MayBlock) {
- constexpr TaskTraits traits = {MayBlock()};
- EXPECT_FALSE(traits.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, traits.priority());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
- EXPECT_TRUE(traits.may_block());
- EXPECT_FALSE(traits.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, WithBaseSyncPrimitives) {
- constexpr TaskTraits traits = {WithBaseSyncPrimitives()};
- EXPECT_FALSE(traits.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, traits.priority());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN, traits.shutdown_behavior());
- EXPECT_FALSE(traits.may_block());
- EXPECT_TRUE(traits.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, MultipleTraits) {
- constexpr TaskTraits traits = {TaskPriority::BACKGROUND,
- TaskShutdownBehavior::BLOCK_SHUTDOWN,
- MayBlock(), WithBaseSyncPrimitives()};
- EXPECT_TRUE(traits.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::BACKGROUND, traits.priority());
- EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN, traits.shutdown_behavior());
- EXPECT_TRUE(traits.may_block());
- EXPECT_TRUE(traits.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, Copy) {
- constexpr TaskTraits traits = {TaskPriority::BACKGROUND,
- TaskShutdownBehavior::BLOCK_SHUTDOWN,
- MayBlock(), WithBaseSyncPrimitives()};
- constexpr TaskTraits traits_copy(traits);
- EXPECT_EQ(traits.priority_set_explicitly(),
- traits_copy.priority_set_explicitly());
- EXPECT_EQ(traits.priority(), traits_copy.priority());
- EXPECT_EQ(traits.shutdown_behavior(), traits_copy.shutdown_behavior());
- EXPECT_EQ(traits.may_block(), traits_copy.may_block());
- EXPECT_EQ(traits.with_base_sync_primitives(),
- traits_copy.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, OverridePriority) {
- constexpr TaskTraits left = {TaskPriority::BACKGROUND};
- constexpr TaskTraits right = {TaskPriority::USER_BLOCKING};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_TRUE(overridden.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_BLOCKING, overridden.priority());
- EXPECT_FALSE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- overridden.shutdown_behavior());
- EXPECT_FALSE(overridden.may_block());
- EXPECT_FALSE(overridden.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, OverrideShutdownBehavior) {
- constexpr TaskTraits left = {TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
- constexpr TaskTraits right = {TaskShutdownBehavior::BLOCK_SHUTDOWN};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_FALSE(overridden.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, overridden.priority());
- EXPECT_TRUE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(TaskShutdownBehavior::BLOCK_SHUTDOWN,
- overridden.shutdown_behavior());
- EXPECT_FALSE(overridden.may_block());
- EXPECT_FALSE(overridden.with_base_sync_primitives());
-}
-
-TEST(TaskSchedulerTaskTraitsTest, OverrideMayBlock) {
- {
- constexpr TaskTraits left = {MayBlock()};
- constexpr TaskTraits right = {};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_FALSE(overridden.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, overridden.priority());
- EXPECT_FALSE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- overridden.shutdown_behavior());
- EXPECT_TRUE(overridden.may_block());
- EXPECT_FALSE(overridden.with_base_sync_primitives());
- }
- {
- constexpr TaskTraits left = {};
- constexpr TaskTraits right = {MayBlock()};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_FALSE(overridden.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, overridden.priority());
- EXPECT_FALSE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- overridden.shutdown_behavior());
- EXPECT_TRUE(overridden.may_block());
- EXPECT_FALSE(overridden.with_base_sync_primitives());
- }
-}
-
-TEST(TaskSchedulerTaskTraitsTest, OverrideWithBaseSyncPrimitives) {
- {
- constexpr TaskTraits left = {WithBaseSyncPrimitives()};
- constexpr TaskTraits right = {};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_FALSE(overridden.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, overridden.priority());
- EXPECT_FALSE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- overridden.shutdown_behavior());
- EXPECT_FALSE(overridden.may_block());
- EXPECT_TRUE(overridden.with_base_sync_primitives());
- }
- {
- constexpr TaskTraits left = {};
- constexpr TaskTraits right = {WithBaseSyncPrimitives()};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_FALSE(overridden.priority_set_explicitly());
- EXPECT_EQ(TaskPriority::USER_VISIBLE, overridden.priority());
- EXPECT_FALSE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(TaskShutdownBehavior::SKIP_ON_SHUTDOWN,
- overridden.shutdown_behavior());
- EXPECT_FALSE(overridden.may_block());
- EXPECT_TRUE(overridden.with_base_sync_primitives());
- }
-}
-
-TEST(TaskSchedulerTaskTraitsTest, OverrideMultipleTraits) {
- constexpr TaskTraits left = {MayBlock(), TaskPriority::BACKGROUND,
- TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
- constexpr TaskTraits right = {WithBaseSyncPrimitives(),
- TaskPriority::USER_BLOCKING};
- constexpr TaskTraits overridden = TaskTraits::Override(left, right);
- EXPECT_TRUE(overridden.priority_set_explicitly());
- EXPECT_EQ(right.priority(), overridden.priority());
- EXPECT_TRUE(overridden.shutdown_behavior_set_explicitly());
- EXPECT_EQ(left.shutdown_behavior(), overridden.shutdown_behavior());
- EXPECT_TRUE(overridden.may_block());
- EXPECT_TRUE(overridden.with_base_sync_primitives());
-}
-
-} // namespace base
diff --git a/base/task_scheduler/task_traits_unittest.nc b/base/task_scheduler/task_traits_unittest.nc
deleted file mode 100644
index 97f9c4b..0000000
--- a/base/task_scheduler/task_traits_unittest.nc
+++ /dev/null
@@ -1,31 +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.
-
-// This is a "No Compile Test" suite.
-// http://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/task_scheduler/task_traits.h"
-
-namespace base {
-
-#if defined(NCTEST_TASK_TRAITS_MULTIPLE_MAY_BLOCK) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
-constexpr TaskTraits traits = {MayBlock(), MayBlock()};
-#elif defined(NCTEST_TASK_TRAITS_MULTIPLE_WITH_BASE_SYNC_PRIMITIVES) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
-constexpr TaskTraits traits = {WithBaseSyncPrimitives(),
- WithBaseSyncPrimitives()};
-#elif defined(NCTEST_TASK_TRAITS_MULTIPLE_TASK_PRIORITY) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
-constexpr TaskTraits traits = {TaskPriority::BACKGROUND,
- TaskPriority::USER_BLOCKING};
-#elif defined(NCTEST_TASK_TRAITS_MULTIPLE_SHUTDOWN_BEHAVIOR) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
-constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN,
- TaskShutdownBehavior::BLOCK_SHUTDOWN};
-#elif defined(NCTEST_TASK_TRAITS_MULTIPLE_SAME_TYPE_MIX) // [r"Multiple arguments of the same type were provided to the constructor of TaskTraits."]
-constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN,
- MayBlock(),
- TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN};
-#elif defined(NCTEST_TASK_TRAITS_INVALID_TYPE) // [r"no matching constructor for initialization of 'const base::TaskTraits'"]
-constexpr TaskTraits traits = {TaskShutdownBehavior::BLOCK_SHUTDOWN, true};
-#endif
-
-} // namespace base
diff --git a/base/task_scheduler/task_unittest.cc b/base/task_scheduler/task_unittest.cc
deleted file mode 100644
index 31a59de..0000000
--- 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/tracked_ref_unittest.cc b/base/task_scheduler/tracked_ref_unittest.cc
deleted file mode 100644
index b793c07..0000000
--- a/base/task_scheduler/tracked_ref_unittest.cc
+++ /dev/null
@@ -1,150 +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/task_scheduler/tracked_ref.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/macros.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/thread.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-class ObjectWithTrackedRefs {
- public:
- ObjectWithTrackedRefs() : tracked_ref_factory_(this) {}
- ~ObjectWithTrackedRefs() { under_destruction_.Set(); }
-
- TrackedRef<ObjectWithTrackedRefs> GetTrackedRef() {
- return tracked_ref_factory_.GetTrackedRef();
- }
-
- bool under_destruction() const { return under_destruction_.IsSet(); }
-
- private:
- // True once ~ObjectWithTrackedRefs() has been initiated.
- AtomicFlag under_destruction_;
-
- TrackedRefFactory<ObjectWithTrackedRefs> tracked_ref_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(ObjectWithTrackedRefs);
-};
-
-} // namespace
-
-// Test that an object with a TrackedRefFactory can be destroyed by a single
-// owner but that its destruction will be blocked on the TrackedRefs being
-// released.
-TEST(TrackedRefTest, TrackedRefObjectDeletion) {
- Thread thread("TrackedRefTestThread");
- thread.Start();
-
- std::unique_ptr<ObjectWithTrackedRefs> obj =
- std::make_unique<ObjectWithTrackedRefs>();
-
- TimeTicks begin = TimeTicks::Now();
-
- thread.task_runner()->PostDelayedTask(
- FROM_HERE,
- BindOnce(
- [](TrackedRef<ObjectWithTrackedRefs> obj) {
- // By the time this kicks in, the object should already be under
- // destruction, but blocked on this TrackedRef being released. This
- // is technically racy (main thread has to run |obj.reset()| and
- // this thread has to observe the side-effects before this delayed
- // task fires). If this ever flakes this expectation could be turned
- // into a while(!obj->under_destruction()); but until that's proven
- // flaky in practice, this expectation is more readable and
- // diagnosable then a hang.
- EXPECT_TRUE(obj->under_destruction());
- },
- obj->GetTrackedRef()),
- TestTimeouts::tiny_timeout());
-
- // This should kick off destruction but block until the above task resolves
- // and releases the TrackedRef.
- obj.reset();
- EXPECT_GE(TimeTicks::Now() - begin, TestTimeouts::tiny_timeout());
-}
-
-TEST(TrackedRefTest, ManyThreadsRacing) {
- constexpr int kNumThreads = 16;
- std::vector<std::unique_ptr<Thread>> threads;
- for (int i = 0; i < kNumThreads; ++i) {
- threads.push_back(std::make_unique<Thread>("TrackedRefTestThread"));
- threads.back()->StartAndWaitForTesting();
- }
-
- std::unique_ptr<ObjectWithTrackedRefs> obj =
- std::make_unique<ObjectWithTrackedRefs>();
-
- // Send a TrackedRef to each thread.
- for (auto& thread : threads) {
- thread->task_runner()->PostTask(
- FROM_HERE, BindOnce(
- [](TrackedRef<ObjectWithTrackedRefs> obj) {
- // Confirm it's still safe to
- // dereference |obj| (and, bonus, that
- // playing with TrackedRefs some more
- // isn't problematic).
- EXPECT_TRUE(obj->GetTrackedRef());
- },
- obj->GetTrackedRef()));
- }
-
- // Initiate destruction racily with the above tasks' execution (they will
- // crash if TrackedRefs aren't WAI).
- obj.reset();
-}
-
-// Test that instantiating and deleting a TrackedRefFactory without ever taking
-// a TrackedRef on it is fine.
-TEST(TrackedRefTest, NoTrackedRefs) {
- ObjectWithTrackedRefs obj;
-}
-
-namespace {
-void ConsumesTrackedRef(TrackedRef<ObjectWithTrackedRefs> obj) {}
-} // namespace
-
-// Test that destroying a TrackedRefFactory which had TrackedRefs in the past
-// that are already gone is WAI.
-TEST(TrackedRefTest, NoPendingTrackedRefs) {
- ObjectWithTrackedRefs obj;
- ConsumesTrackedRef(obj.GetTrackedRef());
-}
-
-TEST(TrackedRefTest, CopyAndMoveSemantics) {
- struct Foo {
- Foo() : factory(this) {}
- TrackedRefFactory<Foo> factory;
- };
- Foo foo;
-
- EXPECT_EQ(1, foo.factory.live_tracked_refs_.SubtleRefCountForDebug());
-
- {
- TrackedRef<Foo> plain = foo.factory.GetTrackedRef();
- EXPECT_EQ(2, foo.factory.live_tracked_refs_.SubtleRefCountForDebug());
-
- TrackedRef<Foo> copy_constructed(plain);
- EXPECT_EQ(3, foo.factory.live_tracked_refs_.SubtleRefCountForDebug());
-
- TrackedRef<Foo> moved_constructed(std::move(copy_constructed));
- EXPECT_EQ(3, foo.factory.live_tracked_refs_.SubtleRefCountForDebug());
- }
-
- EXPECT_EQ(1, foo.factory.live_tracked_refs_.SubtleRefCountForDebug());
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/template_util_unittest.cc b/base/template_util_unittest.cc
deleted file mode 100644
index 2c42445..0000000
--- a/base/template_util_unittest.cc
+++ /dev/null
@@ -1,106 +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/template_util.h"
-
-#include <string>
-
-#include "base/containers/flat_tree.h"
-#include "base/test/move_only_int.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-enum SimpleEnum { SIMPLE_ENUM };
-enum EnumWithExplicitType : uint64_t { ENUM_WITH_EXPLICIT_TYPE };
-enum class ScopedEnum { SCOPED_ENUM };
-enum class ScopedEnumWithOperator { SCOPED_ENUM_WITH_OPERATOR };
-std::ostream& operator<<(std::ostream& os, ScopedEnumWithOperator v) {
- return os;
-}
-struct SimpleStruct {};
-struct StructWithOperator {};
-std::ostream& operator<<(std::ostream& os, const StructWithOperator& v) {
- return os;
-}
-
-// is_non_const_reference<Type>
-static_assert(!is_non_const_reference<int>::value, "IsNonConstReference");
-static_assert(!is_non_const_reference<const int&>::value,
- "IsNonConstReference");
-static_assert(is_non_const_reference<int&>::value, "IsNonConstReference");
-
-// A few standard types that definitely support printing.
-static_assert(internal::SupportsOstreamOperator<int>::value,
- "ints should be printable");
-static_assert(internal::SupportsOstreamOperator<const char*>::value,
- "C strings should be printable");
-static_assert(internal::SupportsOstreamOperator<std::string>::value,
- "std::string should be printable");
-
-// Various kinds of enums operator<< support.
-static_assert(internal::SupportsOstreamOperator<SimpleEnum>::value,
- "simple enum should be printable by value");
-static_assert(internal::SupportsOstreamOperator<const SimpleEnum&>::value,
- "simple enum should be printable by const ref");
-static_assert(internal::SupportsOstreamOperator<EnumWithExplicitType>::value,
- "enum with explicit type should be printable by value");
-static_assert(
- internal::SupportsOstreamOperator<const EnumWithExplicitType&>::value,
- "enum with explicit type should be printable by const ref");
-static_assert(!internal::SupportsOstreamOperator<ScopedEnum>::value,
- "scoped enum should not be printable by value");
-static_assert(!internal::SupportsOstreamOperator<const ScopedEnum&>::value,
- "simple enum should not be printable by const ref");
-static_assert(internal::SupportsOstreamOperator<ScopedEnumWithOperator>::value,
- "scoped enum with operator<< should be printable by value");
-static_assert(
- internal::SupportsOstreamOperator<const ScopedEnumWithOperator&>::value,
- "scoped enum with operator<< should be printable by const ref");
-
-// operator<< support on structs.
-static_assert(!internal::SupportsOstreamOperator<SimpleStruct>::value,
- "simple struct should not be printable by value");
-static_assert(!internal::SupportsOstreamOperator<const SimpleStruct&>::value,
- "simple struct should not be printable by const ref");
-static_assert(internal::SupportsOstreamOperator<StructWithOperator>::value,
- "struct with operator<< should be printable by value");
-static_assert(
- internal::SupportsOstreamOperator<const StructWithOperator&>::value,
- "struct with operator<< should be printable by const ref");
-
-// base::is_trivially_copyable
-class TrivialCopy {
- public:
- TrivialCopy(int d) : data_(d) {}
-
- protected:
- int data_;
-};
-
-class TrivialCopyButWithDestructor : public TrivialCopy {
- public:
- TrivialCopyButWithDestructor(int d) : TrivialCopy(d) {}
- ~TrivialCopyButWithDestructor() { data_ = 0; }
-};
-
-static_assert(base::is_trivially_copyable<TrivialCopy>::value,
- "TrivialCopy should be detected as trivially copyable");
-static_assert(!base::is_trivially_copyable<TrivialCopyButWithDestructor>::value,
- "TrivialCopyButWithDestructor should not be detected as "
- "trivially copyable");
-
-class NoCopy {
- public:
- NoCopy(const NoCopy&) = delete;
-};
-
-static_assert(
- !base::is_trivially_copy_constructible<std::vector<NoCopy>>::value,
- "is_trivially_copy_constructible<std::vector<T>> must be compiled.");
-
-} // namespace
-
-} // namespace base
diff --git a/base/test/BUILD.gn b/base/test/BUILD.gn
deleted file mode 100644
index 576729c..0000000
--- a/base/test/BUILD.gn
+++ /dev/null
@@ -1,443 +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.
-
-import("//build/compiled_action.gni")
-import("//build/config/ui.gni")
-import("//build/config/nacl/config.gni")
-
-if (is_android) {
- import("//build/config/android/rules.gni")
-}
-
-static_library("test_config") {
- testonly = true
- sources = [
- "test_switches.cc",
- "test_switches.h",
- "test_timeouts.cc",
- "test_timeouts.h",
- ]
- deps = [
- "//base",
- ]
-}
-
-static_library("test_support") {
- testonly = true
- sources = [
- "../trace_event/trace_config_memory_test_util.h",
- "android/java_handler_thread_helpers.cc",
- "android/java_handler_thread_helpers.h",
- "android/url_utils.cc",
- "android/url_utils.h",
- "bind_test_util.h",
- "copy_only_int.h",
- "fuzzed_data_provider.cc",
- "fuzzed_data_provider.h",
- "gtest_util.cc",
- "gtest_util.h",
- "gtest_xml_unittest_result_printer.cc",
- "gtest_xml_unittest_result_printer.h",
- "gtest_xml_util.cc",
- "gtest_xml_util.h",
- "histogram_tester.cc",
- "histogram_tester.h",
- "icu_test_util.cc",
- "icu_test_util.h",
- "ios/wait_util.h",
- "ios/wait_util.mm",
- "launcher/test_result.cc",
- "launcher/test_result.h",
- "launcher/test_results_tracker.h",
- "launcher/unit_test_launcher.h",
- "mock_callback.h",
- "mock_chrome_application_mac.h",
- "mock_chrome_application_mac.mm",
- "mock_devices_changed_observer.cc",
- "mock_devices_changed_observer.h",
- "mock_entropy_provider.cc",
- "mock_entropy_provider.h",
- "mock_log.cc",
- "mock_log.h",
- "move_only_int.h",
- "multiprocess_test.h",
- "multiprocess_test_android.cc",
- "null_task_runner.cc",
- "null_task_runner.h",
- "perf_log.cc",
- "perf_log.h",
- "perf_test_suite.cc",
- "perf_test_suite.h",
- "perf_time_logger.cc",
- "perf_time_logger.h",
- "power_monitor_test_base.cc",
- "power_monitor_test_base.h",
- "scoped_command_line.cc",
- "scoped_command_line.h",
- "scoped_environment_variable_override.cc",
- "scoped_environment_variable_override.h",
- "scoped_feature_list.cc",
- "scoped_feature_list.h",
- "scoped_mock_time_message_loop_task_runner.cc",
- "scoped_mock_time_message_loop_task_runner.h",
- "scoped_path_override.cc",
- "scoped_path_override.h",
- "scoped_task_environment.cc",
- "scoped_task_environment.h",
- "sequenced_task_runner_test_template.cc",
- "sequenced_task_runner_test_template.h",
- "simple_test_clock.cc",
- "simple_test_clock.h",
- "simple_test_tick_clock.cc",
- "simple_test_tick_clock.h",
- "task_runner_test_template.cc",
- "task_runner_test_template.h",
- "test_discardable_memory_allocator.cc",
- "test_discardable_memory_allocator.h",
- "test_file_util.cc",
- "test_file_util.h",
- "test_file_util_android.cc",
- "test_file_util_linux.cc",
- "test_file_util_mac.cc",
- "test_file_util_win.cc",
- "test_io_thread.cc",
- "test_io_thread.h",
- "test_listener_ios.h",
- "test_listener_ios.mm",
- "test_message_loop.cc",
- "test_message_loop.h",
- "test_mock_time_task_runner.cc",
- "test_mock_time_task_runner.h",
- "test_pending_task.cc",
- "test_pending_task.h",
- "test_reg_util_win.cc",
- "test_reg_util_win.h",
- "test_shared_memory_util.cc",
- "test_shared_memory_util.h",
- "test_shortcut_win.cc",
- "test_shortcut_win.h",
- "test_simple_task_runner.cc",
- "test_simple_task_runner.h",
- "test_suite.cc",
- "test_suite.h",
- "test_support_android.cc",
- "test_support_android.h",
- "test_support_ios.h",
- "test_support_ios.mm",
- "test_ui_thread_android.cc",
- "test_ui_thread_android.h",
- "thread_test_helper.cc",
- "thread_test_helper.h",
- "trace_event_analyzer.cc",
- "trace_event_analyzer.h",
- "trace_to_file.cc",
- "trace_to_file.h",
- "user_action_tester.cc",
- "user_action_tester.h",
- "values_test_util.cc",
- "values_test_util.h",
- ]
-
- if (is_ios) {
- sources += [ "launcher/unit_test_launcher_ios.cc" ]
- } else if (!is_nacl_nonsfi) {
- sources += [
- "launcher/test_launcher.cc",
- "launcher/test_launcher.h",
- "launcher/test_launcher_tracer.cc",
- "launcher/test_launcher_tracer.h",
- "launcher/test_results_tracker.cc",
- "launcher/unit_test_launcher.cc",
- "multiprocess_test.cc",
- ]
- }
-
- configs += [ "//build/config:precompiled_headers" ]
-
- data = [
- # The isolate needs this script for setting up the test. It's not actually
- # needed to run this target locally.
- "//testing/test_env.py",
- ]
-
- public_deps = [
- ":test_config",
- "//base",
- "//base:base_static",
- "//base:i18n",
- ]
- deps = [
- "//base/third_party/dynamic_annotations",
- "//testing/gmock",
- "//testing/gtest",
- "//third_party/icu:icuuc",
- "//third_party/libxml",
- ]
-
- if (is_posix || is_fuchsia) {
- sources += [
- "scoped_locale.cc",
- "scoped_locale.h",
- "test_file_util_posix.cc",
- ]
- }
-
- if (is_linux) {
- public_deps += [ ":fontconfig_util_linux" ]
- data_deps = [
- "//third_party/test_fonts",
- ]
- if (current_toolchain == host_toolchain) {
- data_deps += [ ":do_generate_fontconfig_caches" ]
- data += [ "$root_out_dir/fontconfig_caches/" ]
- }
- }
-
- if (is_ios) {
- set_sources_assignment_filter([])
- sources += [ "test_file_util_mac.cc" ]
- set_sources_assignment_filter(sources_assignment_filter)
- }
-
- if (is_mac) {
- libs = [ "AppKit.framework" ]
- }
-
- if (is_android) {
- set_sources_assignment_filter([])
- sources += [ "test_file_util_linux.cc" ]
- set_sources_assignment_filter(sources_assignment_filter)
- deps += [
- ":base_unittests_jni_headers",
- ":test_support_jni_headers",
- ]
- public_deps += [ ":test_support_java" ]
- }
-
- if (is_nacl_nonsfi) {
- sources += [
- "launcher/test_launcher.h",
- "launcher/test_result.h",
- "launcher/unit_test_launcher.h",
- "launcher/unit_test_launcher_nacl_nonsfi.cc",
- ]
- sources -= [
- "gtest_xml_util.cc",
- "gtest_xml_util.h",
- "icu_test_util.cc",
- "icu_test_util.h",
- "perf_test_suite.cc",
- "perf_test_suite.h",
- "scoped_path_override.cc",
- "scoped_path_override.h",
- "test_discardable_memory_allocator.cc",
- "test_discardable_memory_allocator.h",
- "test_file_util.cc",
- "test_file_util.h",
- "test_file_util_posix.cc",
- "test_suite.cc",
- "test_suite.h",
- "trace_to_file.cc",
- "trace_to_file.h",
- ]
- public_deps -= [ "//base:i18n" ]
- deps -= [
- "//third_party/icu:icuuc",
- "//third_party/libxml",
- ]
- }
-}
-
-config("perf_test_config") {
- defines = [ "PERF_TEST" ]
-}
-
-# This is a source set instead of a static library because it seems like some
-# linkers get confused when "main" is in a static library, and if you link to
-# this, you always want the object file anyway.
-source_set("test_support_perf") {
- testonly = true
- sources = [
- "run_all_perftests.cc",
- ]
- deps = [
- ":test_support",
- "//base",
- "//testing/gtest",
- ]
-
- public_configs = [ ":perf_test_config" ]
-}
-
-static_library("test_launcher_nacl_nonsfi") {
- testonly = true
- sources = [
- "launcher/test_launcher_nacl_nonsfi.cc",
- "launcher/test_launcher_nacl_nonsfi.h",
- ]
- deps = [
- ":test_support",
- ]
-}
-
-static_library("run_all_unittests") {
- testonly = true
- sources = [
- "run_all_unittests.cc",
- ]
- deps = [
- ":test_support",
- ]
-}
-
-# These sources are linked into both the base_unittests binary and the test
-# shared library target below.
-source_set("native_library_test_utils") {
- testonly = true
- sources = [
- "native_library_test_utils.cc",
- "native_library_test_utils.h",
- ]
-}
-
-# This shared library is dynamically loaded by NativeLibrary unittests.
-shared_library("test_shared_library") {
- testonly = true
- sources = [
- "test_shared_library.cc",
- ]
-
- deps = [
- ":native_library_test_utils",
- ]
-}
-
-static_library("run_all_base_unittests") {
- # Only targets in base should depend on this, targets outside base
- # should depend on run_all_unittests above.
- visibility = [ "//base/*" ]
- testonly = true
- sources = [
- "run_all_base_unittests.cc",
- ]
- deps = [
- ":test_support",
- ]
-}
-
-if (is_linux) {
- source_set("fontconfig_util_linux") {
- sources = [
- "fontconfig_util_linux.cc",
- "fontconfig_util_linux.h",
- ]
- deps = [
- "//base",
- "//third_party/fontconfig",
- ]
- }
-
- if (current_toolchain == host_toolchain) {
- executable("generate_fontconfig_caches") {
- testonly = true
- sources = [
- "generate_fontconfig_caches.cc",
- ]
- deps = [
- ":fontconfig_util_linux",
- "//base",
- "//build/config:exe_and_shlib_deps",
- ]
- }
-
- compiled_action("do_generate_fontconfig_caches") {
- testonly = true
- tool = ":generate_fontconfig_caches"
- data_deps = [
- "//third_party/test_fonts",
- ]
- args = []
- outputs = [
- "$root_out_dir/fontconfig_caches/STAMP",
- ]
- }
- }
-
- shared_library("malloc_wrapper") {
- testonly = true
- sources = [
- "malloc_wrapper.cc",
- ]
- deps = [
- "//base",
- "//build/config:exe_and_shlib_deps",
- ]
- }
-}
-
-if (is_android) {
- generate_jni("base_unittests_jni_headers") {
- sources = [
- "android/java/src/org/chromium/base/ContentUriTestUtils.java",
- "android/java/src/org/chromium/base/JavaHandlerThreadHelpers.java",
- "android/java/src/org/chromium/base/TestUiThread.java",
- ]
- jni_package = "base"
- }
-
- generate_jni("test_support_jni_headers") {
- sources = [
- "android/java/src/org/chromium/base/MainReturnCodeResult.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java",
- "android/javatests/src/org/chromium/base/test/util/UrlUtils.java",
- ]
- jni_package = "base"
- }
-
- android_library("test_support_java") {
- testonly = true
- deps = [
- "//base:base_java",
- "//testing/android/native_test:native_main_runner_java",
- "//third_party/android_tools:android_support_annotations_java",
- "//third_party/jsr-305:jsr_305_javalib",
- ]
- srcjar_deps = [ ":test_support_java_aidl" ]
- java_files = [
- "android/java/src/org/chromium/base/MainReturnCodeResult.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientLauncher.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientService.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientService0.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientService1.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientService2.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientService3.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientService4.java",
- "android/java/src/org/chromium/base/MultiprocessTestClientServiceDelegate.java",
- ]
- }
-
- android_aidl("test_support_java_aidl") {
- testonly = true
- import_include = [
- "android/java/src",
- "//base/android/java/src",
- ]
- sources = [
- "android/java/src/org/chromium/base/ITestCallback.aidl",
- "android/java/src/org/chromium/base/ITestController.aidl",
- ]
- }
-}
-
-# Trivial executable which outputs space-delimited argv to stdout,
-# used for testing.
-executable("test_child_process") {
- testonly = true
- sources = [
- "test_child_process.cc",
- ]
- deps = [
- "//build/config:exe_and_shlib_deps",
- ]
-}
diff --git a/base/test/histogram_tester_unittest.cc b/base/test/histogram_tester_unittest.cc
deleted file mode 100644
index e49ed97..0000000
--- a/base/test/histogram_tester_unittest.cc
+++ /dev/null
@@ -1,130 +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/histogram_tester.h"
-
-#include <memory>
-
-#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());
-}
-
-} // namespace base
diff --git a/base/test/mock_callback_unittest.cc b/base/test/mock_callback_unittest.cc
deleted file mode 100644
index c5f109f..0000000
--- 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/scoped_feature_list_unittest.cc b/base/test/scoped_feature_list_unittest.cc
deleted file mode 100644
index 03d9897..0000000
--- a/base/test/scoped_feature_list_unittest.cc
+++ /dev/null
@@ -1,297 +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/scoped_feature_list.h"
-
-#include <map>
-#include <string>
-#include <utility>
-
-#include "base/metrics/field_trial.h"
-#include "base/metrics/field_trial_params.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace test {
-
-namespace {
-
-const Feature kTestFeature1{"TestFeature1", FEATURE_DISABLED_BY_DEFAULT};
-const Feature kTestFeature2{"TestFeature2", FEATURE_DISABLED_BY_DEFAULT};
-
-void ExpectFeatures(const std::string& enabled_features,
- const std::string& disabled_features) {
- FeatureList* list = FeatureList::GetInstance();
- std::string actual_enabled_features;
- std::string actual_disabled_features;
-
- list->GetFeatureOverrides(&actual_enabled_features,
- &actual_disabled_features);
-
- EXPECT_EQ(enabled_features, actual_enabled_features);
- EXPECT_EQ(disabled_features, actual_disabled_features);
-}
-
-} // namespace
-
-class ScopedFeatureListTest : public testing::Test {
- public:
- ScopedFeatureListTest() {
- // Clear default feature list.
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- feature_list->InitializeFromCommandLine(std::string(), std::string());
- original_feature_list_ = FeatureList::ClearInstanceForTesting();
- FeatureList::SetInstance(std::move(feature_list));
- }
-
- ~ScopedFeatureListTest() override {
- // Restore feature list.
- if (original_feature_list_) {
- FeatureList::ClearInstanceForTesting();
- FeatureList::RestoreInstanceForTesting(std::move(original_feature_list_));
- }
- }
-
- private:
- // Save the present FeatureList and restore it after test finish.
- std::unique_ptr<FeatureList> original_feature_list_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedFeatureListTest);
-};
-
-TEST_F(ScopedFeatureListTest, BasicScoped) {
- ExpectFeatures(std::string(), std::string());
- EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
- {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitFromCommandLine("TestFeature1", std::string());
- ExpectFeatures("TestFeature1", std::string());
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- }
- ExpectFeatures(std::string(), std::string());
- EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
-}
-
-TEST_F(ScopedFeatureListTest, EnableWithFeatureParameters) {
- const char kParam1[] = "param_1";
- const char kParam2[] = "param_2";
- const char kValue1[] = "value_1";
- const char kValue2[] = "value_2";
- std::map<std::string, std::string> parameters;
- parameters[kParam1] = kValue1;
- parameters[kParam2] = kValue2;
-
- ExpectFeatures(std::string(), std::string());
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
- FieldTrial::ActiveGroups active_groups;
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_EQ(0u, active_groups.size());
-
- {
- test::ScopedFeatureList feature_list;
-
- feature_list.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_EQ(kValue1,
- GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
- EXPECT_EQ(kValue2,
- GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
- active_groups.clear();
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_EQ(1u, active_groups.size());
- }
-
- ExpectFeatures(std::string(), std::string());
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam1));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam2));
- active_groups.clear();
- FieldTrialList::GetActiveFieldTrialGroups(&active_groups);
- EXPECT_EQ(0u, active_groups.size());
-}
-
-TEST_F(ScopedFeatureListTest, OverrideWithFeatureParameters) {
- FieldTrialList field_trial_list(nullptr);
- scoped_refptr<FieldTrial> trial =
- FieldTrialList::CreateFieldTrial("foo", "bar");
- const char kParam[] = "param_1";
- const char kValue[] = "value_1";
- std::map<std::string, std::string> parameters;
- parameters[kParam] = kValue;
-
- test::ScopedFeatureList feature_list1;
- feature_list1.InitFromCommandLine("TestFeature1<foo,TestFeature2",
- std::string());
-
- // Check initial state.
- ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
- EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
-
- {
- // Override feature with existing field trial.
- test::ScopedFeatureList feature_list2;
-
- feature_list2.InitAndEnableFeatureWithParameters(kTestFeature1, parameters);
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
- EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
- EXPECT_NE(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
- }
-
- // Check that initial state is restored.
- ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
- EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
-
- {
- // Override feature with no existing field trial.
- test::ScopedFeatureList feature_list2;
-
- feature_list2.InitAndEnableFeatureWithParameters(kTestFeature2, parameters);
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
- EXPECT_EQ(kValue, GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
- EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_NE(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
- }
-
- // Check that initial state is restored.
- ExpectFeatures("TestFeature1<foo,TestFeature2", std::string());
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_TRUE(FeatureList::IsEnabled(kTestFeature2));
- EXPECT_EQ(trial.get(), FeatureList::GetFieldTrial(kTestFeature1));
- EXPECT_EQ(nullptr, FeatureList::GetFieldTrial(kTestFeature2));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature1, kParam));
- EXPECT_EQ("", GetFieldTrialParamValueByFeature(kTestFeature2, kParam));
-}
-
-TEST_F(ScopedFeatureListTest, EnableFeatureOverrideDisable) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitWithFeatures({}, {kTestFeature1});
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({kTestFeature1}, {});
- ExpectFeatures("TestFeature1", std::string());
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideNotMakeDuplicate) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitWithFeatures({}, {kTestFeature1});
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({}, {kTestFeature1});
- ExpectFeatures(std::string(), "TestFeature1");
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitFromCommandLine("*TestFeature1", std::string());
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({kTestFeature1}, {});
- ExpectFeatures("TestFeature1", std::string());
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDefault2) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitFromCommandLine("*TestFeature1", std::string());
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({}, {kTestFeature1});
- ExpectFeatures(std::string(), "TestFeature1");
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithEnabledFieldTrial) {
- test::ScopedFeatureList feature_list1;
-
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- FieldTrialList field_trial_list(nullptr);
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A");
- feature_list->RegisterFieldTrialOverride(
- kTestFeature1.name, FeatureList::OVERRIDE_ENABLE_FEATURE, trial);
- feature_list1.InitWithFeatureList(std::move(feature_list));
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({kTestFeature1}, {});
- ExpectFeatures("TestFeature1", std::string());
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideFeatureWithDisabledFieldTrial) {
- test::ScopedFeatureList feature_list1;
-
- std::unique_ptr<FeatureList> feature_list(new FeatureList);
- FieldTrialList field_trial_list(nullptr);
- FieldTrial* trial = FieldTrialList::CreateFieldTrial("TrialExample", "A");
- feature_list->RegisterFieldTrialOverride(
- kTestFeature1.name, FeatureList::OVERRIDE_DISABLE_FEATURE, trial);
- feature_list1.InitWithFeatureList(std::move(feature_list));
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({kTestFeature1}, {});
- ExpectFeatures("TestFeature1", std::string());
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitWithFeatures({}, {kTestFeature1});
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({}, {kTestFeature2});
- EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature1));
- EXPECT_FALSE(FeatureList::IsEnabled(kTestFeature2));
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingFeature2) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitWithFeatures({}, {kTestFeature1});
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({kTestFeature2}, {});
- ExpectFeatures("TestFeature2", "TestFeature1");
- }
-}
-
-TEST_F(ScopedFeatureListTest, FeatureOverrideKeepsOtherExistingDefaultFeature) {
- test::ScopedFeatureList feature_list1;
- feature_list1.InitFromCommandLine("*TestFeature1", std::string());
-
- {
- test::ScopedFeatureList feature_list2;
- feature_list2.InitWithFeatures({}, {kTestFeature2});
- ExpectFeatures("*TestFeature1", "TestFeature2");
- }
-}
-
-} // namespace test
-} // namespace base
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 b08323d..0000000
--- 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_task_environment_unittest.cc b/base/test/scoped_task_environment_unittest.cc
deleted file mode 100644
index 1c10d69..0000000
--- a/base/test/scoped_task_environment_unittest.cc
+++ /dev/null
@@ -1,324 +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/scoped_task_environment.h"
-
-#include <memory>
-
-#include "base/atomicops.h"
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/synchronization/atomic_flag.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/task_scheduler/post_task.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequence_local_storage_slot.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/tick_clock.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include <unistd.h>
-#include "base/files/file_descriptor_watcher_posix.h"
-#endif // defined(OS_POSIX)
-
-namespace base {
-namespace test {
-
-namespace {
-
-class ScopedTaskEnvironmentTest
- : public testing::TestWithParam<ScopedTaskEnvironment::MainThreadType> {};
-
-void VerifyRunUntilIdleDidNotReturnAndSetFlag(
- AtomicFlag* run_until_idle_returned,
- AtomicFlag* task_ran) {
- EXPECT_FALSE(run_until_idle_returned->IsSet());
- task_ran->Set();
-}
-
-void RunUntilIdleTest(
- ScopedTaskEnvironment::MainThreadType main_thread_type,
- ScopedTaskEnvironment::ExecutionMode execution_control_mode) {
- AtomicFlag run_until_idle_returned;
- ScopedTaskEnvironment scoped_task_environment(main_thread_type,
- execution_control_mode);
-
- AtomicFlag first_main_thread_task_ran;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, BindOnce(&VerifyRunUntilIdleDidNotReturnAndSetFlag,
- Unretained(&run_until_idle_returned),
- Unretained(&first_main_thread_task_ran)));
-
- AtomicFlag first_task_scheduler_task_ran;
- PostTask(FROM_HERE, BindOnce(&VerifyRunUntilIdleDidNotReturnAndSetFlag,
- Unretained(&run_until_idle_returned),
- Unretained(&first_task_scheduler_task_ran)));
-
- AtomicFlag second_task_scheduler_task_ran;
- AtomicFlag second_main_thread_task_ran;
- PostTaskAndReply(FROM_HERE,
- BindOnce(&VerifyRunUntilIdleDidNotReturnAndSetFlag,
- Unretained(&run_until_idle_returned),
- Unretained(&second_task_scheduler_task_ran)),
- BindOnce(&VerifyRunUntilIdleDidNotReturnAndSetFlag,
- Unretained(&run_until_idle_returned),
- Unretained(&second_main_thread_task_ran)));
-
- scoped_task_environment.RunUntilIdle();
- run_until_idle_returned.Set();
-
- EXPECT_TRUE(first_main_thread_task_ran.IsSet());
- EXPECT_TRUE(first_task_scheduler_task_ran.IsSet());
- EXPECT_TRUE(second_task_scheduler_task_ran.IsSet());
- EXPECT_TRUE(second_main_thread_task_ran.IsSet());
-}
-
-} // namespace
-
-TEST_P(ScopedTaskEnvironmentTest, QueuedRunUntilIdle) {
- RunUntilIdleTest(GetParam(), ScopedTaskEnvironment::ExecutionMode::QUEUED);
-}
-
-TEST_P(ScopedTaskEnvironmentTest, AsyncRunUntilIdle) {
- RunUntilIdleTest(GetParam(), ScopedTaskEnvironment::ExecutionMode::ASYNC);
-}
-
-// Verify that tasks posted to an ExecutionMode::QUEUED ScopedTaskEnvironment do
-// not run outside of RunUntilIdle().
-TEST_P(ScopedTaskEnvironmentTest, QueuedTasksDoNotRunOutsideOfRunUntilIdle) {
- ScopedTaskEnvironment scoped_task_environment(
- GetParam(), ScopedTaskEnvironment::ExecutionMode::QUEUED);
-
- AtomicFlag run_until_idle_called;
- PostTask(FROM_HERE, BindOnce(
- [](AtomicFlag* run_until_idle_called) {
- EXPECT_TRUE(run_until_idle_called->IsSet());
- },
- Unretained(&run_until_idle_called)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- run_until_idle_called.Set();
- scoped_task_environment.RunUntilIdle();
-
- AtomicFlag other_run_until_idle_called;
- PostTask(FROM_HERE, BindOnce(
- [](AtomicFlag* other_run_until_idle_called) {
- EXPECT_TRUE(other_run_until_idle_called->IsSet());
- },
- Unretained(&other_run_until_idle_called)));
- PlatformThread::Sleep(TestTimeouts::tiny_timeout());
- other_run_until_idle_called.Set();
- scoped_task_environment.RunUntilIdle();
-}
-
-// Verify that a task posted to an ExecutionMode::ASYNC ScopedTaskEnvironment
-// can run without a call to RunUntilIdle().
-TEST_P(ScopedTaskEnvironmentTest, AsyncTasksRunAsTheyArePosted) {
- ScopedTaskEnvironment scoped_task_environment(
- GetParam(), ScopedTaskEnvironment::ExecutionMode::ASYNC);
-
- WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- PostTask(FROM_HERE,
- BindOnce([](WaitableEvent* task_ran) { task_ran->Signal(); },
- Unretained(&task_ran)));
- task_ran.Wait();
-}
-
-// Verify that a task posted to an ExecutionMode::ASYNC ScopedTaskEnvironment
-// after a call to RunUntilIdle() can run without another call to
-// RunUntilIdle().
-TEST_P(ScopedTaskEnvironmentTest,
- AsyncTasksRunAsTheyArePostedAfterRunUntilIdle) {
- ScopedTaskEnvironment scoped_task_environment(
- GetParam(), ScopedTaskEnvironment::ExecutionMode::ASYNC);
-
- scoped_task_environment.RunUntilIdle();
-
- WaitableEvent task_ran(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- PostTask(FROM_HERE,
- BindOnce([](WaitableEvent* task_ran) { task_ran->Signal(); },
- Unretained(&task_ran)));
- task_ran.Wait();
-}
-
-TEST_P(ScopedTaskEnvironmentTest, DelayedTasks) {
- // Use a QUEUED execution-mode environment, so that no tasks are actually
- // executed until RunUntilIdle()/FastForwardBy() are invoked.
- ScopedTaskEnvironment scoped_task_environment(
- GetParam(), ScopedTaskEnvironment::ExecutionMode::QUEUED);
-
- subtle::Atomic32 counter = 0;
-
- constexpr base::TimeDelta kShortTaskDelay = TimeDelta::FromDays(1);
- // Should run only in MOCK_TIME environment when time is fast-forwarded.
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- Bind(
- [](subtle::Atomic32* counter) {
- subtle::NoBarrier_AtomicIncrement(counter, 4);
- },
- Unretained(&counter)),
- kShortTaskDelay);
- // TODO(gab): This currently doesn't run because the TaskScheduler's clock
- // isn't mocked but it should be.
- PostDelayedTask(FROM_HERE,
- Bind(
- [](subtle::Atomic32* counter) {
- subtle::NoBarrier_AtomicIncrement(counter, 128);
- },
- Unretained(&counter)),
- kShortTaskDelay);
-
- constexpr base::TimeDelta kLongTaskDelay = TimeDelta::FromDays(7);
- // Same as first task, longer delays to exercise
- // FastForwardUntilNoTasksRemain().
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- Bind(
- [](subtle::Atomic32* counter) {
- subtle::NoBarrier_AtomicIncrement(counter, 8);
- },
- Unretained(&counter)),
- TimeDelta::FromDays(5));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- Bind(
- [](subtle::Atomic32* counter) {
- subtle::NoBarrier_AtomicIncrement(counter, 16);
- },
- Unretained(&counter)),
- kLongTaskDelay);
-
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, Bind(
- [](subtle::Atomic32* counter) {
- subtle::NoBarrier_AtomicIncrement(counter, 1);
- },
- Unretained(&counter)));
- PostTask(FROM_HERE, Bind(
- [](subtle::Atomic32* counter) {
- subtle::NoBarrier_AtomicIncrement(counter, 2);
- },
- Unretained(&counter)));
-
- // This expectation will fail flakily if the preceding PostTask() is executed
- // asynchronously, indicating a problem with the QUEUED execution mode.
- int expected_value = 0;
- EXPECT_EQ(expected_value, counter);
-
- // RunUntilIdle() should process non-delayed tasks only in all queues.
- scoped_task_environment.RunUntilIdle();
- expected_value += 1;
- expected_value += 2;
- EXPECT_EQ(expected_value, counter);
-
- if (GetParam() == ScopedTaskEnvironment::MainThreadType::MOCK_TIME) {
- // Delay inferior to the delay of the first posted task.
- constexpr base::TimeDelta kInferiorTaskDelay = TimeDelta::FromSeconds(1);
- static_assert(kInferiorTaskDelay < kShortTaskDelay,
- "|kInferiorTaskDelay| should be "
- "set to a value inferior to the first posted task's delay.");
- scoped_task_environment.FastForwardBy(kInferiorTaskDelay);
- EXPECT_EQ(expected_value, counter);
-
- scoped_task_environment.FastForwardBy(kShortTaskDelay - kInferiorTaskDelay);
- expected_value += 4;
- EXPECT_EQ(expected_value, counter);
-
- scoped_task_environment.FastForwardUntilNoTasksRemain();
- expected_value += 8;
- expected_value += 16;
- EXPECT_EQ(expected_value, counter);
- }
-}
-
-// Regression test for https://crbug.com/824770.
-TEST_P(ScopedTaskEnvironmentTest, SupportsSequenceLocalStorageOnMainThread) {
- ScopedTaskEnvironment scoped_task_environment(
- GetParam(), ScopedTaskEnvironment::ExecutionMode::ASYNC);
-
- SequenceLocalStorageSlot<int> sls_slot;
- sls_slot.Set(5);
- EXPECT_EQ(5, sls_slot.Get());
-}
-
-#if defined(OS_POSIX)
-TEST_F(ScopedTaskEnvironmentTest, SupportsFileDescriptorWatcherOnIOMainThread) {
- ScopedTaskEnvironment scoped_task_environment(
- ScopedTaskEnvironment::MainThreadType::IO,
- ScopedTaskEnvironment::ExecutionMode::ASYNC);
-
- int pipe_fds_[2];
- ASSERT_EQ(0, pipe(pipe_fds_));
-
- RunLoop run_loop;
-
- // The write end of a newly created pipe is immediately writable.
- auto controller = FileDescriptorWatcher::WatchWritable(
- pipe_fds_[1], run_loop.QuitClosure());
-
- // This will hang if the notification doesn't occur as expected.
- run_loop.Run();
-}
-#endif // defined(OS_POSIX)
-
-// Verify that the TickClock returned by
-// |ScopedTaskEnvironment::GetMockTickClock| gets updated when the
-// FastForward(By|UntilNoTasksRemain) functions are called.
-TEST_F(ScopedTaskEnvironmentTest, FastForwardAdvanceTickClock) {
- // Use a QUEUED execution-mode environment, so that no tasks are actually
- // executed until RunUntilIdle()/FastForwardBy() are invoked.
- ScopedTaskEnvironment scoped_task_environment(
- ScopedTaskEnvironment::MainThreadType::MOCK_TIME,
- ScopedTaskEnvironment::ExecutionMode::QUEUED);
-
- constexpr base::TimeDelta kShortTaskDelay = TimeDelta::FromDays(1);
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::DoNothing(),
- kShortTaskDelay);
-
- constexpr base::TimeDelta kLongTaskDelay = TimeDelta::FromDays(7);
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(FROM_HERE, base::DoNothing(),
- kLongTaskDelay);
-
- const base::TickClock* tick_clock =
- scoped_task_environment.GetMockTickClock();
- base::TimeTicks tick_clock_ref = tick_clock->NowTicks();
-
- // Make sure that |FastForwardBy| advances the clock.
- scoped_task_environment.FastForwardBy(kShortTaskDelay);
- EXPECT_EQ(kShortTaskDelay, tick_clock->NowTicks() - tick_clock_ref);
-
- // Make sure that |FastForwardUntilNoTasksRemain| advances the clock.
- scoped_task_environment.FastForwardUntilNoTasksRemain();
- EXPECT_EQ(kLongTaskDelay, tick_clock->NowTicks() - tick_clock_ref);
-
- // Fast-forwarding to a time at which there's no tasks should also advance the
- // clock.
- scoped_task_environment.FastForwardBy(kLongTaskDelay);
- EXPECT_EQ(kLongTaskDelay * 2, tick_clock->NowTicks() - tick_clock_ref);
-}
-
-INSTANTIATE_TEST_CASE_P(
- MainThreadDefault,
- ScopedTaskEnvironmentTest,
- ::testing::Values(ScopedTaskEnvironment::MainThreadType::DEFAULT));
-INSTANTIATE_TEST_CASE_P(
- MainThreadMockTime,
- ScopedTaskEnvironmentTest,
- ::testing::Values(ScopedTaskEnvironment::MainThreadType::MOCK_TIME));
-INSTANTIATE_TEST_CASE_P(
- MainThreadUI,
- ScopedTaskEnvironmentTest,
- ::testing::Values(ScopedTaskEnvironment::MainThreadType::UI));
-INSTANTIATE_TEST_CASE_P(
- MainThreadIO,
- ScopedTaskEnvironmentTest,
- ::testing::Values(ScopedTaskEnvironment::MainThreadType::IO));
-
-} // namespace test
-} // namespace base
diff --git a/base/test/test_mock_time_task_runner_unittest.cc b/base/test/test_mock_time_task_runner_unittest.cc
deleted file mode 100644
index 04be466..0000000
--- a/base/test/test_mock_time_task_runner_unittest.cc
+++ /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.
-
-#include "base/test/test_mock_time_task_runner.h"
-
-#include "base/cancelable_callback.h"
-#include "base/memory/ref_counted.h"
-#include "base/run_loop.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_timeouts.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-// Basic usage should work the same from default and bound
-// TestMockTimeTaskRunners.
-TEST(TestMockTimeTaskRunnerTest, Basic) {
- static constexpr TestMockTimeTaskRunner::Type kTestCases[] = {
- TestMockTimeTaskRunner::Type::kStandalone,
- TestMockTimeTaskRunner::Type::kBoundToThread};
-
- for (auto type : kTestCases) {
- SCOPED_TRACE(static_cast<int>(type));
-
- auto mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(type);
- int counter = 0;
-
- mock_time_task_runner->PostTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 1; }, Unretained(&counter)));
- mock_time_task_runner->PostTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 32; }, Unretained(&counter)));
- mock_time_task_runner->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 256; }, Unretained(&counter)),
- TimeDelta::FromSeconds(3));
- mock_time_task_runner->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 64; }, Unretained(&counter)),
- TimeDelta::FromSeconds(1));
- mock_time_task_runner->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 1024; },
- Unretained(&counter)),
- TimeDelta::FromMinutes(20));
- mock_time_task_runner->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 4096; },
- Unretained(&counter)),
- TimeDelta::FromDays(20));
-
- int expected_value = 0;
- EXPECT_EQ(expected_value, counter);
- mock_time_task_runner->RunUntilIdle();
- expected_value += 1;
- expected_value += 32;
- EXPECT_EQ(expected_value, counter);
-
- mock_time_task_runner->RunUntilIdle();
- EXPECT_EQ(expected_value, counter);
-
- mock_time_task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
- expected_value += 64;
- EXPECT_EQ(expected_value, counter);
-
- mock_time_task_runner->FastForwardBy(TimeDelta::FromSeconds(5));
- expected_value += 256;
- EXPECT_EQ(expected_value, counter);
-
- mock_time_task_runner->FastForwardUntilNoTasksRemain();
- expected_value += 1024;
- expected_value += 4096;
- EXPECT_EQ(expected_value, counter);
- }
-}
-
-// A default TestMockTimeTaskRunner shouldn't result in a thread association.
-TEST(TestMockTimeTaskRunnerTest, DefaultUnbound) {
- auto unbound_mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
- EXPECT_FALSE(ThreadTaskRunnerHandle::IsSet());
- EXPECT_FALSE(SequencedTaskRunnerHandle::IsSet());
- EXPECT_DEATH_IF_SUPPORTED({ RunLoop().RunUntilIdle(); }, "");
-}
-
-TEST(TestMockTimeTaskRunnerTest, RunLoopDriveableWhenBound) {
- auto bound_mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
- TestMockTimeTaskRunner::Type::kBoundToThread);
-
- int counter = 0;
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 1; }, Unretained(&counter)));
- ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 32; }, Unretained(&counter)));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 256; }, Unretained(&counter)),
- TimeDelta::FromSeconds(3));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 64; }, Unretained(&counter)),
- TimeDelta::FromSeconds(1));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 1024; }, Unretained(&counter)),
- TimeDelta::FromMinutes(20));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 4096; }, Unretained(&counter)),
- TimeDelta::FromDays(20));
-
- int expected_value = 0;
- EXPECT_EQ(expected_value, counter);
- RunLoop().RunUntilIdle();
- expected_value += 1;
- expected_value += 32;
- EXPECT_EQ(expected_value, counter);
-
- RunLoop().RunUntilIdle();
- EXPECT_EQ(expected_value, counter);
-
- {
- RunLoop run_loop;
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitClosure(), TimeDelta::FromSeconds(1));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 8192; },
- Unretained(&counter)),
- TimeDelta::FromSeconds(1));
-
- // The QuitClosure() should be ordered between the 64 and the 8192
- // increments and should preempt the latter.
- run_loop.Run();
- expected_value += 64;
- EXPECT_EQ(expected_value, counter);
-
- // Running until idle should process the 8192 increment whose delay has
- // expired in the previous Run().
- RunLoop().RunUntilIdle();
- expected_value += 8192;
- EXPECT_EQ(expected_value, counter);
- }
-
- {
- RunLoop run_loop;
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitWhenIdleClosure(), TimeDelta::FromSeconds(5));
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE,
- base::Bind([](int* counter) { *counter += 16384; },
- Unretained(&counter)),
- TimeDelta::FromSeconds(5));
-
- // The QuitWhenIdleClosure() shouldn't preempt equally delayed tasks and as
- // such the 16384 increment should be processed before quitting.
- run_loop.Run();
- expected_value += 256;
- expected_value += 16384;
- EXPECT_EQ(expected_value, counter);
- }
-
- // Process the remaining tasks (note: do not mimic this elsewhere,
- // TestMockTimeTaskRunner::FastForwardUntilNoTasksRemain() is a better API to
- // do this, this is just done here for the purpose of extensively testing the
- // RunLoop approach).
- RunLoop run_loop;
- ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, run_loop.QuitWhenIdleClosure(), TimeDelta::FromDays(50));
-
- run_loop.Run();
- expected_value += 1024;
- expected_value += 4096;
- EXPECT_EQ(expected_value, counter);
-}
-
-// Regression test that receiving the quit-when-idle signal when already empty
-// works as intended (i.e. that |TestMockTimeTaskRunner::tasks_lock_cv| is
-// properly signaled).
-TEST(TestMockTimeTaskRunnerTest, RunLoopQuitFromIdle) {
- auto bound_mock_time_task_runner = MakeRefCounted<TestMockTimeTaskRunner>(
- TestMockTimeTaskRunner::Type::kBoundToThread);
-
- Thread quitting_thread("quitting thread");
- quitting_thread.Start();
-
- RunLoop run_loop;
- quitting_thread.task_runner()->PostDelayedTask(
- FROM_HERE, run_loop.QuitWhenIdleClosure(), TestTimeouts::tiny_timeout());
- run_loop.Run();
-}
-
-TEST(TestMockTimeTaskRunnerTest, TakePendingTasks) {
- auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
- task_runner->PostTask(FROM_HERE, Bind([]() {}));
- EXPECT_TRUE(task_runner->HasPendingTask());
- EXPECT_EQ(1u, task_runner->TakePendingTasks().size());
- EXPECT_FALSE(task_runner->HasPendingTask());
-}
-
-TEST(TestMockTimeTaskRunnerTest, CancelPendingTask) {
- auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
- CancelableClosure task1(Bind([]() {}));
- task_runner->PostDelayedTask(FROM_HERE, task1.callback(),
- TimeDelta::FromSeconds(1));
- EXPECT_TRUE(task_runner->HasPendingTask());
- EXPECT_EQ(1u, task_runner->GetPendingTaskCount());
- EXPECT_EQ(TimeDelta::FromSeconds(1), task_runner->NextPendingTaskDelay());
- task1.Cancel();
- EXPECT_FALSE(task_runner->HasPendingTask());
-
- CancelableClosure task2(Bind([]() {}));
- task_runner->PostDelayedTask(FROM_HERE, task2.callback(),
- TimeDelta::FromSeconds(1));
- task2.Cancel();
- EXPECT_EQ(0u, task_runner->GetPendingTaskCount());
-
- CancelableClosure task3(Bind([]() {}));
- task_runner->PostDelayedTask(FROM_HERE, task3.callback(),
- TimeDelta::FromSeconds(1));
- task3.Cancel();
- EXPECT_EQ(TimeDelta::Max(), task_runner->NextPendingTaskDelay());
-
- CancelableClosure task4(Bind([]() {}));
- task_runner->PostDelayedTask(FROM_HERE, task4.callback(),
- TimeDelta::FromSeconds(1));
- task4.Cancel();
- EXPECT_TRUE(task_runner->TakePendingTasks().empty());
-}
-
-TEST(TestMockTimeTaskRunnerTest, NoFastForwardToCancelledTask) {
- auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
- TimeTicks start_time = task_runner->NowTicks();
- CancelableClosure task(Bind([]() {}));
- task_runner->PostDelayedTask(FROM_HERE, task.callback(),
- TimeDelta::FromSeconds(1));
- EXPECT_EQ(TimeDelta::FromSeconds(1), task_runner->NextPendingTaskDelay());
- task.Cancel();
- task_runner->FastForwardUntilNoTasksRemain();
- EXPECT_EQ(start_time, task_runner->NowTicks());
-}
-
-TEST(TestMockTimeTaskRunnerTest, AdvanceMockTickClockDoesNotRunTasks) {
- auto task_runner = MakeRefCounted<TestMockTimeTaskRunner>();
- TimeTicks start_time = task_runner->NowTicks();
- task_runner->PostTask(FROM_HERE, BindOnce([]() { ADD_FAILURE(); }));
- task_runner->PostDelayedTask(FROM_HERE, BindOnce([]() { ADD_FAILURE(); }),
- TimeDelta::FromSeconds(1));
-
- task_runner->AdvanceMockTickClock(TimeDelta::FromSeconds(3));
- EXPECT_EQ(start_time + TimeDelta::FromSeconds(3), task_runner->NowTicks());
- EXPECT_EQ(2u, task_runner->GetPendingTaskCount());
-}
-
-} // namespace base
diff --git a/base/test/test_pending_task_unittest.cc b/base/test/test_pending_task_unittest.cc
deleted file mode 100644
index 6e01c8c..0000000
--- 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_reg_util_win_unittest.cc b/base/test/test_reg_util_win_unittest.cc
deleted file mode 100644
index ca3bc99..0000000
--- a/base/test/test_reg_util_win_unittest.cc
+++ /dev/null
@@ -1,133 +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_reg_util_win.h"
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace registry_util {
-
-namespace {
-const wchar_t kTestKeyPath[] = L"Software\\Chromium\\Foo\\Baz\\TestKey";
-const wchar_t kTestValueName[] = L"TestValue";
-} // namespace
-
-class RegistryOverrideManagerTest : public testing::Test {
- protected:
- RegistryOverrideManagerTest() {
- // We assign a fake test key path to our test RegistryOverrideManager
- // so we don't interfere with any actual RegistryOverrideManagers running
- // on the system. This fake path will be auto-deleted by other
- // RegistryOverrideManagers in case we crash.
- fake_test_key_root_ = registry_util::GenerateTempKeyPath();
-
- // Ensure a clean test environment.
- base::win::RegKey key(HKEY_CURRENT_USER);
- key.DeleteKey(fake_test_key_root_.c_str());
- key.DeleteKey(kTestKeyPath);
- }
-
- ~RegistryOverrideManagerTest() override {
- base::win::RegKey key(HKEY_CURRENT_USER);
- key.DeleteKey(fake_test_key_root_.c_str());
- }
-
- void AssertKeyExists(const base::string16& key_path) {
- base::win::RegKey key;
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ))
- << key_path << " does not exist.";
- }
-
- void AssertKeyAbsent(const base::string16& key_path) {
- base::win::RegKey key;
- ASSERT_NE(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, key_path.c_str(), KEY_READ))
- << key_path << " exists but it should not.";
- }
-
- void CreateKey(const base::string16& key_path) {
- base::win::RegKey key;
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_CURRENT_USER, key_path.c_str(), KEY_ALL_ACCESS));
- }
-
- base::string16 FakeOverrideManagerPath(const base::Time& time) {
- return fake_test_key_root_ + L"\\" +
- base::Int64ToString16(time.ToInternalValue());
- }
-
- void CreateManager(const base::Time& timestamp) {
- manager_.reset(new RegistryOverrideManager(timestamp, fake_test_key_root_));
- manager_->OverrideRegistry(HKEY_CURRENT_USER);
- }
-
- base::string16 fake_test_key_root_;
- std::unique_ptr<RegistryOverrideManager> manager_;
-};
-
-TEST_F(RegistryOverrideManagerTest, Basic) {
- ASSERT_NO_FATAL_FAILURE(CreateManager(base::Time::Now()));
-
- base::win::RegKey create_key;
- EXPECT_EQ(ERROR_SUCCESS,
- create_key.Create(HKEY_CURRENT_USER, kTestKeyPath, KEY_ALL_ACCESS));
- EXPECT_TRUE(create_key.Valid());
- EXPECT_EQ(ERROR_SUCCESS, create_key.WriteValue(kTestValueName, 42));
- create_key.Close();
-
- ASSERT_NO_FATAL_FAILURE(AssertKeyExists(kTestKeyPath));
-
- DWORD value;
- base::win::RegKey read_key;
- EXPECT_EQ(ERROR_SUCCESS,
- read_key.Open(HKEY_CURRENT_USER, kTestKeyPath, KEY_READ));
- EXPECT_TRUE(read_key.Valid());
- EXPECT_EQ(ERROR_SUCCESS, read_key.ReadValueDW(kTestValueName, &value));
- EXPECT_EQ(42u, value);
- read_key.Close();
-
- manager_.reset();
-
- ASSERT_NO_FATAL_FAILURE(AssertKeyAbsent(kTestKeyPath));
-}
-
-TEST_F(RegistryOverrideManagerTest, DeleteStaleKeys) {
- base::Time::Exploded kTestTimeExploded = {2013, 11, 1, 4, 0, 0, 0, 0};
- base::Time kTestTime;
- EXPECT_TRUE(base::Time::FromUTCExploded(kTestTimeExploded, &kTestTime));
-
- base::string16 path_garbage = fake_test_key_root_ + L"\\Blah";
- base::string16 path_very_stale =
- FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromDays(100));
- base::string16 path_stale =
- FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromDays(5));
- base::string16 path_current =
- FakeOverrideManagerPath(kTestTime - base::TimeDelta::FromMinutes(1));
- base::string16 path_future =
- FakeOverrideManagerPath(kTestTime + base::TimeDelta::FromMinutes(1));
-
- ASSERT_NO_FATAL_FAILURE(CreateKey(path_garbage));
- ASSERT_NO_FATAL_FAILURE(CreateKey(path_very_stale));
- ASSERT_NO_FATAL_FAILURE(CreateKey(path_stale));
- ASSERT_NO_FATAL_FAILURE(CreateKey(path_current));
- ASSERT_NO_FATAL_FAILURE(CreateKey(path_future));
-
- ASSERT_NO_FATAL_FAILURE(CreateManager(kTestTime));
- manager_.reset();
-
- ASSERT_NO_FATAL_FAILURE(AssertKeyAbsent(path_garbage));
- ASSERT_NO_FATAL_FAILURE(AssertKeyAbsent(path_very_stale));
- ASSERT_NO_FATAL_FAILURE(AssertKeyAbsent(path_stale));
- ASSERT_NO_FATAL_FAILURE(AssertKeyExists(path_current));
- ASSERT_NO_FATAL_FAILURE(AssertKeyExists(path_future));
-}
-
-} // namespace registry_util
diff --git a/base/test/trace_event_analyzer_unittest.cc b/base/test/trace_event_analyzer_unittest.cc
deleted file mode 100644
index 6461b0f..0000000
--- 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/user_action_tester_unittest.cc b/base/test/user_action_tester_unittest.cc
deleted file mode 100644
index a51849f..0000000
--- a/base/test/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/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/third_party/dynamic_annotations/BUILD.gn b/base/third_party/dynamic_annotations/BUILD.gn
deleted file mode 100644
index 0fc4bf7..0000000
--- a/base/third_party/dynamic_annotations/BUILD.gn
+++ /dev/null
@@ -1,27 +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.
-
-if (is_nacl) {
- # Native client doesn't need dynamic annotations, so we provide a
- # dummy target in order for clients to not have to special-case the
- # dependency.
- source_set("dynamic_annotations") {
- sources = [
- "dynamic_annotations.h",
- ]
- }
-} else {
- # Should be static library, see documentation on //base:base for discussion.
- static_library("dynamic_annotations") {
- sources = [
- "../valgrind/valgrind.h",
- "dynamic_annotations.c",
- "dynamic_annotations.h",
- ]
- if (is_android && !is_debug) {
- configs -= [ "//build/config/compiler:default_optimization" ]
- configs += [ "//build/config/compiler:optimize_max" ]
- }
- }
-}
diff --git a/base/third_party/libevent/BUILD.gn b/base/third_party/libevent/BUILD.gn
deleted file mode 100644
index e934454..0000000
--- a/base/third_party/libevent/BUILD.gn
+++ /dev/null
@@ -1,80 +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.
-
-import("//build/config/nacl/config.gni")
-
-static_library("libevent") {
- sources = [
- "buffer.c",
- "evbuffer.c",
- "evdns.c",
- "evdns.h",
- "event-config.h",
- "event-internal.h",
- "event.c",
- "event.h",
- "event_tagging.c",
- "evhttp.h",
- "evrpc-internal.h",
- "evrpc.c",
- "evrpc.h",
- "evsignal.h",
- "evutil.c",
- "evutil.h",
- "http-internal.h",
- "http.c",
- "log.c",
- "log.h",
- "min_heap.h",
- "poll.c",
- "select.c",
- "signal.c",
- "strlcpy-internal.h",
- "strlcpy.c",
- ]
-
- defines = [ "HAVE_CONFIG_H" ]
-
- if (is_mac || is_ios) {
- sources += [
- "kqueue.c",
- "mac/config.h",
- "mac/event-config.h",
- ]
- include_dirs = [ "mac" ]
- } else if (is_linux) {
- sources += [
- "epoll.c",
- "linux/config.h",
- "linux/event-config.h",
- ]
- include_dirs = [ "linux" ]
- } else if (is_android) {
- sources += [
- "android/config.h",
- "android/event-config.h",
- "epoll.c",
- ]
- include_dirs = [ "android" ]
- } else if (is_nacl_nonsfi) {
- sources -= [
- "evdns.c",
- "event_tagging.c",
- "evrpc.c",
- "http.c",
- "select.c",
- "signal.c",
- ]
- sources += [
- "nacl_nonsfi/config.h",
- "nacl_nonsfi/event-config.h",
- "nacl_nonsfi/random.c",
- "nacl_nonsfi/signal_stub.c",
- ]
- include_dirs = [ "nacl_nonsfi" ]
- }
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
-}
diff --git a/base/third_party/symbolize/BUILD.gn b/base/third_party/symbolize/BUILD.gn
deleted file mode 100644
index 0dc7c2f..0000000
--- a/base/third_party/symbolize/BUILD.gn
+++ /dev/null
@@ -1,36 +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.
-
-import("//build/config/compiler/compiler.gni")
-
-declare_args() {
- # Stack traces will not include function names. Instead they will contain
- # file and offset information that can be used with
- # tools/valgrind/asan/asan_symbolize.py. By piping stderr through this script,
- # and also enabling symbol_level = 2, you can get much more detailed stack
- # traces with file names and line numbers, even in non-ASAN builds.
- print_unsymbolized_stack_traces = is_asan || is_lsan || is_msan || is_tsan
-}
-
-static_library("symbolize") {
- visibility = [ "//base/*" ]
- sources = [
- "config.h",
- "demangle.cc",
- "demangle.h",
- "glog/logging.h",
- "glog/raw_logging.h",
- "symbolize.cc",
- "symbolize.h",
- "utilities.h",
- ]
-
- defines = []
- if (print_unsymbolized_stack_traces) {
- defines += [ "PRINT_UNSYMBOLIZED_STACK_TRACES" ]
- }
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
-}
diff --git a/base/third_party/xdg_mime/BUILD.gn b/base/third_party/xdg_mime/BUILD.gn
deleted file mode 100644
index ac9e2c9..0000000
--- a/base/third_party/xdg_mime/BUILD.gn
+++ /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.
-
-static_library("xdg_mime") {
- visibility = [ "//base/*" ]
- sources = [
- "xdgmime.c",
- "xdgmime.h",
- "xdgmimealias.c",
- "xdgmimealias.h",
- "xdgmimecache.c",
- "xdgmimecache.h",
- "xdgmimeglob.c",
- "xdgmimeglob.h",
- "xdgmimeicon.c",
- "xdgmimeicon.h",
- "xdgmimeint.c",
- "xdgmimeint.h",
- "xdgmimemagic.c",
- "xdgmimemagic.h",
- "xdgmimeparent.c",
- "xdgmimeparent.h",
- ]
-
- configs -= [ "//build/config/compiler:chromium_code" ]
- configs += [ "//build/config/compiler:no_chromium_code" ]
-}
diff --git a/base/third_party/xdg_user_dirs/BUILD.gn b/base/third_party/xdg_user_dirs/BUILD.gn
deleted file mode 100644
index a5626e9..0000000
--- a/base/third_party/xdg_user_dirs/BUILD.gn
+++ /dev/null
@@ -1,11 +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.
-
-static_library("xdg_user_dirs") {
- visibility = [ "//base/*" ]
- sources = [
- "xdg_user_dir_lookup.cc",
- "xdg_user_dir_lookup.h",
- ]
-}
diff --git a/base/thread_annotations_unittest.cc b/base/thread_annotations_unittest.cc
deleted file mode 100644
index b4aafef..0000000
--- a/base/thread_annotations_unittest.cc
+++ /dev/null
@@ -1,58 +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.
-
-#include "thread_annotations.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-class LOCKABLE Lock {
- public:
- void Acquire() EXCLUSIVE_LOCK_FUNCTION() {}
- void Release() UNLOCK_FUNCTION() {}
-};
-
-class SCOPED_LOCKABLE AutoLock {
- public:
- AutoLock(Lock& lock) EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) {
- lock.Acquire();
- }
- ~AutoLock() UNLOCK_FUNCTION() { lock_.Release(); }
-
- private:
- Lock& lock_;
-};
-
-class ThreadSafe {
- public:
- void ExplicitIncrement();
- void ImplicitIncrement();
-
- private:
- Lock lock_;
- int counter_ GUARDED_BY(lock_);
-};
-
-void ThreadSafe::ExplicitIncrement() {
- lock_.Acquire();
- ++counter_;
- lock_.Release();
-}
-
-void ThreadSafe::ImplicitIncrement() {
- AutoLock auto_lock(lock_);
- counter_++;
-}
-
-TEST(ThreadAnnotationsTest, ExplicitIncrement) {
- ThreadSafe thread_safe;
- thread_safe.ExplicitIncrement();
-}
-TEST(ThreadAnnotationsTest, ImplicitIncrement) {
- ThreadSafe thread_safe;
- thread_safe.ImplicitIncrement();
-}
-
-} // anonymous namespace
diff --git a/base/thread_annotations_unittest.nc b/base/thread_annotations_unittest.nc
deleted file mode 100644
index ea64a7e..0000000
--- a/base/thread_annotations_unittest.nc
+++ /dev/null
@@ -1,71 +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.
-
-// This is a "No Compile Test" suite.
-// https://dev.chromium.org/developers/testing/no-compile-tests
-
-#include "base/thread_annotations.h"
-
-namespace {
-
-class LOCKABLE Lock {
- public:
- void Acquire() EXCLUSIVE_LOCK_FUNCTION() {}
- void Release() UNLOCK_FUNCTION() {}
-};
-
-class SCOPED_LOCKABLE AutoLock {
- public:
- AutoLock(Lock& lock) EXCLUSIVE_LOCK_FUNCTION(lock) : lock_(lock) {
- lock.Acquire();
- }
- ~AutoLock() UNLOCK_FUNCTION() { lock_.Release(); }
-
- private:
- Lock& lock_;
-};
-class ThreadSafe {
- public:
- void BuggyIncrement();
- private:
- Lock lock_;
- int counter_ GUARDED_BY(lock_);
-};
-
-#if defined(NCTEST_LOCK_WITHOUT_UNLOCK) // [r"fatal error: mutex 'lock_' is still held at the end of function"]
-
-void ThreadSafe::BuggyIncrement() {
- lock_.Acquire();
- ++counter_;
- // Forgot to release the lock.
-}
-
-#elif defined(NCTEST_ACCESS_WITHOUT_LOCK) // [r"fatal error: writing variable 'counter_' requires holding mutex 'lock_' exclusively"]
-
-void ThreadSafe::BuggyIncrement() {
- // Member access without holding the lock guarding it.
- ++counter_;
-}
-
-#elif defined(NCTEST_ACCESS_WITHOUT_SCOPED_LOCK) // [r"fatal error: writing variable 'counter_' requires holding mutex 'lock_' exclusively"]
-
-void ThreadSafe::BuggyIncrement() {
- {
- AutoLock auto_lock(lock_);
- // The AutoLock will go out of scope before the guarded member access.
- }
- ++counter_;
-}
-
-#elif defined(NCTEST_GUARDED_BY_WRONG_TYPE) // [r"fatal error: 'guarded_by' attribute requires arguments whose type is annotated"]
-
-int not_lockable;
-int global_counter GUARDED_BY(not_lockable);
-
-// Defined to avoid link error.
-void ThreadSafe::BuggyIncrement() { }
-
-#endif
-
-} // anonymous namespace
diff --git a/base/threading/platform_thread_unittest.cc b/base/threading/platform_thread_unittest.cc
deleted file mode 100644
index 968f0e0..0000000
--- a/base/threading/platform_thread_unittest.cc
+++ /dev/null
@@ -1,367 +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/compiler_specific.h"
-#include "base/macros.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_POSIX)
-#include "base/threading/platform_thread_internal_posix.h"
-#elif defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace base {
-
-// Trivial tests that thread runs and doesn't crash on create, join, or detach -
-
-namespace {
-
-class TrivialThread : public PlatformThread::Delegate {
- public:
- TrivialThread() : run_event_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- void ThreadMain() override { run_event_.Signal(); }
-
- WaitableEvent& run_event() { return run_event_; }
-
- private:
- WaitableEvent run_event_;
-
- DISALLOW_COPY_AND_ASSIGN(TrivialThread);
-};
-
-} // namespace
-
-TEST(PlatformThreadTest, TrivialJoin) {
- TrivialThread thread;
- PlatformThreadHandle handle;
-
- ASSERT_FALSE(thread.run_event().IsSignaled());
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
- PlatformThread::Join(handle);
- ASSERT_TRUE(thread.run_event().IsSignaled());
-}
-
-TEST(PlatformThreadTest, TrivialJoinTimesTen) {
- TrivialThread thread[10];
- PlatformThreadHandle handle[arraysize(thread)];
-
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_FALSE(thread[n].run_event().IsSignaled());
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
- for (size_t n = 0; n < arraysize(thread); n++)
- PlatformThread::Join(handle[n]);
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_TRUE(thread[n].run_event().IsSignaled());
-}
-
-// The following detach tests are by nature racy. The run_event approximates the
-// end and termination of the thread, but threads could persist shortly after
-// the test completes.
-TEST(PlatformThreadTest, TrivialDetach) {
- TrivialThread thread;
- PlatformThreadHandle handle;
-
- ASSERT_FALSE(thread.run_event().IsSignaled());
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
- PlatformThread::Detach(handle);
- thread.run_event().Wait();
-}
-
-TEST(PlatformThreadTest, TrivialDetachTimesTen) {
- TrivialThread thread[10];
- PlatformThreadHandle handle[arraysize(thread)];
-
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_FALSE(thread[n].run_event().IsSignaled());
- for (size_t n = 0; n < arraysize(thread); n++) {
- ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
- PlatformThread::Detach(handle[n]);
- }
- for (size_t n = 0; n < arraysize(thread); n++)
- thread[n].run_event().Wait();
-}
-
-// Tests of basic thread functions ---------------------------------------------
-
-namespace {
-
-class FunctionTestThread : public PlatformThread::Delegate {
- public:
- FunctionTestThread()
- : thread_id_(kInvalidThreadId),
- termination_ready_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- terminate_thread_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- done_(false) {}
- ~FunctionTestThread() override {
- EXPECT_TRUE(terminate_thread_.IsSignaled())
- << "Need to mark thread for termination and join the underlying thread "
- << "before destroying a FunctionTestThread as it owns the "
- << "WaitableEvent blocking the underlying thread's main.";
- }
-
- // Grabs |thread_id_|, runs an optional test on that thread, signals
- // |termination_ready_|, and then waits for |terminate_thread_| to be
- // signaled before exiting.
- void ThreadMain() override {
- thread_id_ = PlatformThread::CurrentId();
- EXPECT_NE(thread_id_, kInvalidThreadId);
-
- // Make sure that the thread ID is the same across calls.
- EXPECT_EQ(thread_id_, PlatformThread::CurrentId());
-
- // Run extra tests.
- RunTest();
-
- termination_ready_.Signal();
- terminate_thread_.Wait();
-
- done_ = true;
- }
-
- PlatformThreadId thread_id() const {
- EXPECT_TRUE(termination_ready_.IsSignaled()) << "Thread ID still unknown";
- return thread_id_;
- }
-
- bool IsRunning() const {
- return termination_ready_.IsSignaled() && !done_;
- }
-
- // Blocks until this thread is started and ready to be terminated.
- void WaitForTerminationReady() { termination_ready_.Wait(); }
-
- // Marks this thread for termination (callers must then join this thread to be
- // guaranteed of termination).
- void MarkForTermination() { terminate_thread_.Signal(); }
-
- private:
- // Runs an optional test on the newly created thread.
- virtual void RunTest() {}
-
- PlatformThreadId thread_id_;
-
- mutable WaitableEvent termination_ready_;
- WaitableEvent terminate_thread_;
- bool done_;
-
- DISALLOW_COPY_AND_ASSIGN(FunctionTestThread);
-};
-
-} // namespace
-
-TEST(PlatformThreadTest, Function) {
- PlatformThreadId main_thread_id = PlatformThread::CurrentId();
-
- FunctionTestThread thread;
- PlatformThreadHandle handle;
-
- ASSERT_FALSE(thread.IsRunning());
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
- thread.WaitForTerminationReady();
- ASSERT_TRUE(thread.IsRunning());
- EXPECT_NE(thread.thread_id(), main_thread_id);
-
- thread.MarkForTermination();
- PlatformThread::Join(handle);
- ASSERT_FALSE(thread.IsRunning());
-
- // Make sure that the thread ID is the same across calls.
- EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
-}
-
-TEST(PlatformThreadTest, FunctionTimesTen) {
- PlatformThreadId main_thread_id = PlatformThread::CurrentId();
-
- FunctionTestThread thread[10];
- PlatformThreadHandle handle[arraysize(thread)];
-
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_FALSE(thread[n].IsRunning());
-
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_TRUE(PlatformThread::Create(0, &thread[n], &handle[n]));
- for (size_t n = 0; n < arraysize(thread); n++)
- thread[n].WaitForTerminationReady();
-
- for (size_t n = 0; n < arraysize(thread); n++) {
- ASSERT_TRUE(thread[n].IsRunning());
- EXPECT_NE(thread[n].thread_id(), main_thread_id);
-
- // Make sure no two threads get the same ID.
- for (size_t i = 0; i < n; ++i) {
- EXPECT_NE(thread[i].thread_id(), thread[n].thread_id());
- }
- }
-
- for (size_t n = 0; n < arraysize(thread); n++)
- thread[n].MarkForTermination();
- for (size_t n = 0; n < arraysize(thread); n++)
- PlatformThread::Join(handle[n]);
- for (size_t n = 0; n < arraysize(thread); n++)
- ASSERT_FALSE(thread[n].IsRunning());
-
- // Make sure that the thread ID is the same across calls.
- EXPECT_EQ(main_thread_id, PlatformThread::CurrentId());
-}
-
-namespace {
-
-const ThreadPriority kThreadPriorityTestValues[] = {
-// The order should be higher to lower to cover as much cases as possible on
-// Linux trybots running without CAP_SYS_NICE permission.
-#if !defined(OS_ANDROID)
- // PlatformThread::GetCurrentThreadPriority() on Android does not support
- // REALTIME_AUDIO case. See http://crbug.com/505474.
- ThreadPriority::REALTIME_AUDIO,
-#endif
- ThreadPriority::DISPLAY,
- // This redundant BACKGROUND priority is to test backgrounding from other
- // priorities, and unbackgrounding.
- ThreadPriority::BACKGROUND,
- ThreadPriority::NORMAL,
- ThreadPriority::BACKGROUND};
-
-class ThreadPriorityTestThread : public FunctionTestThread {
- public:
- explicit ThreadPriorityTestThread(ThreadPriority priority)
- : priority_(priority) {}
- ~ThreadPriorityTestThread() override = default;
-
- private:
- void RunTest() override {
- // Confirm that the current thread's priority is as expected.
- EXPECT_EQ(ThreadPriority::NORMAL,
- PlatformThread::GetCurrentThreadPriority());
-
- // Alter and verify the current thread's priority.
- PlatformThread::SetCurrentThreadPriority(priority_);
- EXPECT_EQ(priority_, PlatformThread::GetCurrentThreadPriority());
- }
-
- const ThreadPriority priority_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadPriorityTestThread);
-};
-
-} // namespace
-
-// Test changing a created thread's priority (which has different semantics on
-// some platforms).
-TEST(PlatformThreadTest, ThreadPriorityCurrentThread) {
- const bool increase_priority_allowed =
- PlatformThread::CanIncreaseCurrentThreadPriority();
-
-// Bump the priority in order to verify that new threads are started with normal
-// priority. Skip this on Mac since this platform doesn't allow changing the
-// priority of the main thread. Also skip this on platforms that don't allow
-// increasing the priority of a thread.
-#if !defined(OS_MACOSX)
- if (increase_priority_allowed)
- PlatformThread::SetCurrentThreadPriority(ThreadPriority::DISPLAY);
-#endif
-
- // Toggle each supported priority on the thread and confirm it affects it.
- for (size_t i = 0; i < arraysize(kThreadPriorityTestValues); ++i) {
- if (!increase_priority_allowed &&
- kThreadPriorityTestValues[i] >
- PlatformThread::GetCurrentThreadPriority()) {
- continue;
- }
-
- ThreadPriorityTestThread thread(kThreadPriorityTestValues[i]);
- PlatformThreadHandle handle;
-
- ASSERT_FALSE(thread.IsRunning());
- ASSERT_TRUE(PlatformThread::Create(0, &thread, &handle));
- thread.WaitForTerminationReady();
- ASSERT_TRUE(thread.IsRunning());
-
- thread.MarkForTermination();
- PlatformThread::Join(handle);
- ASSERT_FALSE(thread.IsRunning());
- }
-}
-
-// This tests internal PlatformThread APIs used under some POSIX platforms,
-// with the exception of Mac OS X, iOS and Fuchsia.
-#if defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) && \
- !defined(OS_FUCHSIA)
-TEST(PlatformThreadTest, GetNiceValueToThreadPriority) {
- using internal::NiceValueToThreadPriority;
- using internal::kThreadPriorityToNiceValueMap;
-
- EXPECT_EQ(ThreadPriority::BACKGROUND,
- kThreadPriorityToNiceValueMap[0].priority);
- EXPECT_EQ(ThreadPriority::NORMAL,
- kThreadPriorityToNiceValueMap[1].priority);
- EXPECT_EQ(ThreadPriority::DISPLAY,
- kThreadPriorityToNiceValueMap[2].priority);
- EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
- kThreadPriorityToNiceValueMap[3].priority);
-
- static const int kBackgroundNiceValue =
- kThreadPriorityToNiceValueMap[0].nice_value;
- static const int kNormalNiceValue =
- kThreadPriorityToNiceValueMap[1].nice_value;
- static const int kDisplayNiceValue =
- kThreadPriorityToNiceValueMap[2].nice_value;
- static const int kRealtimeAudioNiceValue =
- kThreadPriorityToNiceValueMap[3].nice_value;
-
- // The tests below assume the nice values specified in the map are within
- // the range below (both ends exclusive).
- static const int kHighestNiceValue = 19;
- static const int kLowestNiceValue = -20;
-
- EXPECT_GT(kHighestNiceValue, kBackgroundNiceValue);
- EXPECT_GT(kBackgroundNiceValue, kNormalNiceValue);
- EXPECT_GT(kNormalNiceValue, kDisplayNiceValue);
- EXPECT_GT(kDisplayNiceValue, kRealtimeAudioNiceValue);
- EXPECT_GT(kRealtimeAudioNiceValue, kLowestNiceValue);
-
- EXPECT_EQ(ThreadPriority::BACKGROUND,
- NiceValueToThreadPriority(kHighestNiceValue));
- EXPECT_EQ(ThreadPriority::BACKGROUND,
- NiceValueToThreadPriority(kBackgroundNiceValue + 1));
- EXPECT_EQ(ThreadPriority::BACKGROUND,
- NiceValueToThreadPriority(kBackgroundNiceValue));
- EXPECT_EQ(ThreadPriority::BACKGROUND,
- NiceValueToThreadPriority(kNormalNiceValue + 1));
- EXPECT_EQ(ThreadPriority::NORMAL,
- NiceValueToThreadPriority(kNormalNiceValue));
- EXPECT_EQ(ThreadPriority::NORMAL,
- NiceValueToThreadPriority(kDisplayNiceValue + 1));
- EXPECT_EQ(ThreadPriority::DISPLAY,
- NiceValueToThreadPriority(kDisplayNiceValue));
- EXPECT_EQ(ThreadPriority::DISPLAY,
- NiceValueToThreadPriority(kRealtimeAudioNiceValue + 1));
- EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
- NiceValueToThreadPriority(kRealtimeAudioNiceValue));
- EXPECT_EQ(ThreadPriority::REALTIME_AUDIO,
- NiceValueToThreadPriority(kLowestNiceValue));
-}
-#endif // defined(OS_POSIX) && !defined(OS_MACOSX) && !defined(OS_IOS) &&
- // !defined(OS_FUCHSIA)
-
-TEST(PlatformThreadTest, SetHugeThreadName) {
- // Construct an excessively long thread name.
- std::string long_name(1024, 'a');
-
- // SetName has no return code, so just verify that implementations
- // don't [D]CHECK().
- PlatformThread::SetName(long_name);
-}
-
-} // 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 319327d..0000000
--- 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/scoped_blocking_call_unittest.cc b/base/threading/scoped_blocking_call_unittest.cc
deleted file mode 100644
index 5e030f3..0000000
--- a/base/threading/scoped_blocking_call_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/threading/scoped_blocking_call.h"
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/test/gtest_util.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class MockBlockingObserver : public internal::BlockingObserver {
- public:
- MockBlockingObserver() = default;
-
- MOCK_METHOD1(BlockingStarted, void(BlockingType));
- MOCK_METHOD0(BlockingTypeUpgraded, void());
- MOCK_METHOD0(BlockingEnded, void());
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MockBlockingObserver);
-};
-
-class ScopedBlockingCallTest : public testing::Test {
- protected:
- ScopedBlockingCallTest() {
- internal::SetBlockingObserverForCurrentThread(&observer_);
- }
-
- ~ScopedBlockingCallTest() override {
- internal::ClearBlockingObserverForTesting();
- }
-
- testing::StrictMock<MockBlockingObserver> observer_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ScopedBlockingCallTest);
-};
-
-} // namespace
-
-TEST_F(ScopedBlockingCallTest, MayBlock) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
- ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST_F(ScopedBlockingCallTest, WillBlock) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK));
- ScopedBlockingCall scoped_blocking_call(BlockingType::WILL_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST_F(ScopedBlockingCallTest, MayBlockWillBlock) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
- ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
-
- {
- EXPECT_CALL(observer_, BlockingTypeUpgraded());
- ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
- }
-
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST_F(ScopedBlockingCallTest, WillBlockMayBlock) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK));
- ScopedBlockingCall scoped_blocking_call_a(BlockingType::WILL_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
-
- { ScopedBlockingCall scoped_blocking_call_b(BlockingType::MAY_BLOCK); }
-
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST_F(ScopedBlockingCallTest, MayBlockMayBlock) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
- ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
-
- { ScopedBlockingCall scoped_blocking_call_b(BlockingType::MAY_BLOCK); }
-
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST_F(ScopedBlockingCallTest, WillBlockWillBlock) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::WILL_BLOCK));
- ScopedBlockingCall scoped_blocking_call_a(BlockingType::WILL_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
-
- { ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK); }
-
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST_F(ScopedBlockingCallTest, MayBlockWillBlockTwice) {
- EXPECT_CALL(observer_, BlockingStarted(BlockingType::MAY_BLOCK));
- ScopedBlockingCall scoped_blocking_call_a(BlockingType::MAY_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
-
- {
- EXPECT_CALL(observer_, BlockingTypeUpgraded());
- ScopedBlockingCall scoped_blocking_call_b(BlockingType::WILL_BLOCK);
- testing::Mock::VerifyAndClear(&observer_);
-
- {
- ScopedBlockingCall scoped_blocking_call_c(BlockingType::MAY_BLOCK);
- ScopedBlockingCall scoped_blocking_call_d(BlockingType::WILL_BLOCK);
- }
- }
-
- EXPECT_CALL(observer_, BlockingEnded());
-}
-
-TEST(ScopedBlockingCallDestructionOrderTest, InvalidDestructionOrder) {
- auto scoped_blocking_call_a =
- std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK);
- auto scoped_blocking_call_b =
- std::make_unique<ScopedBlockingCall>(BlockingType::WILL_BLOCK);
-
- EXPECT_DCHECK_DEATH({ scoped_blocking_call_a.reset(); });
-}
-
-} // namespace base
diff --git a/base/threading/sequence_local_storage_map_unittest.cc b/base/threading/sequence_local_storage_map_unittest.cc
deleted file mode 100644
index a45bbc3..0000000
--- a/base/threading/sequence_local_storage_map_unittest.cc
+++ /dev/null
@@ -1,117 +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/sequence_local_storage_map.h"
-
-#include <memory>
-#include <utility>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace internal {
-
-namespace {
-
-constexpr int kSlotId = 1;
-
-class SetOnDestroy {
- public:
- SetOnDestroy(bool* was_destroyed_ptr)
- : was_destroyed_ptr_(was_destroyed_ptr) {
- DCHECK(was_destroyed_ptr_);
- DCHECK(!(*was_destroyed_ptr_));
- }
- ~SetOnDestroy() {
- DCHECK(!(*was_destroyed_ptr_));
- *was_destroyed_ptr_ = true;
- }
-
- private:
- bool* const was_destroyed_ptr_;
-
- DISALLOW_COPY_AND_ASSIGN(SetOnDestroy);
-};
-
-template <typename T, typename... Args>
-SequenceLocalStorageMap::ValueDestructorPair CreateValueDestructorPair(
- Args... args) {
- T* value = new T(args...);
- SequenceLocalStorageMap::ValueDestructorPair::DestructorFunc* destructor =
- [](void* ptr) { std::default_delete<T>()(static_cast<T*>(ptr)); };
-
- SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair{
- value, destructor};
-
- return value_destructor_pair;
-}
-
-} // namespace
-
-// Verify that setting a value in the SequenceLocalStorageMap, then getting
-// it will yield the same value.
-TEST(SequenceLocalStorageMapTest, SetGet) {
- SequenceLocalStorageMap sequence_local_storage_map;
- ScopedSetSequenceLocalStorageMapForCurrentThread
- scoped_sequence_local_storage_map(&sequence_local_storage_map);
-
- SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
- CreateValueDestructorPair<int>(5);
-
- sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
-
- EXPECT_EQ(*static_cast<int*>(sequence_local_storage_map.Get(kSlotId)), 5);
-}
-
-// Verify that the destructor is called on a value stored in the
-// SequenceLocalStorageMap when SequenceLocalStorageMap is destroyed.
-TEST(SequenceLocalStorageMapTest, Destructor) {
- bool set_on_destruction = false;
-
- {
- SequenceLocalStorageMap sequence_local_storage_map;
- ScopedSetSequenceLocalStorageMapForCurrentThread
- scoped_sequence_local_storage_map(&sequence_local_storage_map);
-
- SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
- CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
-
- sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
- }
-
- EXPECT_TRUE(set_on_destruction);
-}
-
-// Verify that overwriting a value already in the SequenceLocalStorageMap
-// calls value's destructor.
-TEST(SequenceLocalStorageMapTest, DestructorCalledOnSetOverwrite) {
- bool set_on_destruction = false;
- bool set_on_destruction2 = false;
- {
- SequenceLocalStorageMap sequence_local_storage_map;
- ScopedSetSequenceLocalStorageMapForCurrentThread
- scoped_sequence_local_storage_map(&sequence_local_storage_map);
-
- SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair =
- CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction);
- SequenceLocalStorageMap::ValueDestructorPair value_destructor_pair2 =
- CreateValueDestructorPair<SetOnDestroy>(&set_on_destruction2);
-
- sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair));
-
- ASSERT_FALSE(set_on_destruction);
-
- // Overwrites the old value in the slot.
- sequence_local_storage_map.Set(kSlotId, std::move(value_destructor_pair2));
-
- // Destructor should've been called for the old value in the slot, and not
- // yet called for the new value.
- EXPECT_TRUE(set_on_destruction);
- EXPECT_FALSE(set_on_destruction2);
- }
- EXPECT_TRUE(set_on_destruction2);
-}
-
-} // namespace internal
-} // namespace base
diff --git a/base/threading/sequence_local_storage_slot_unittest.cc b/base/threading/sequence_local_storage_slot_unittest.cc
deleted file mode 100644
index 4a9f6a9..0000000
--- a/base/threading/sequence_local_storage_slot_unittest.cc
+++ /dev/null
@@ -1,143 +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/sequence_local_storage_slot.h"
-
-#include <utility>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/threading/sequence_local_storage_map.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class SequenceLocalStorageSlotTest : public testing::Test {
- protected:
- SequenceLocalStorageSlotTest()
- : scoped_sequence_local_storage_(&sequence_local_storage_) {}
-
- internal::SequenceLocalStorageMap sequence_local_storage_;
- internal::ScopedSetSequenceLocalStorageMapForCurrentThread
- scoped_sequence_local_storage_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(SequenceLocalStorageSlotTest);
-};
-
-} // namespace
-
-// Verify that a value stored with Set() can be retrieved with Get().
-TEST_F(SequenceLocalStorageSlotTest, GetSet) {
- SequenceLocalStorageSlot<int> slot;
- slot.Set(5);
- EXPECT_EQ(slot.Get(), 5);
-}
-
-// Verify that setting an object in a SequenceLocalStorageSlot creates a copy
-// of that object independent of the original one.
-TEST_F(SequenceLocalStorageSlotTest, SetObjectIsIndependent) {
- bool should_be_false = false;
-
- SequenceLocalStorageSlot<bool> slot;
-
- slot.Set(should_be_false);
-
- EXPECT_FALSE(slot.Get());
- slot.Get() = true;
- EXPECT_TRUE(slot.Get());
-
- EXPECT_NE(should_be_false, slot.Get());
-}
-
-// Verify that multiple slots work and that calling Get after overwriting
-// a value in a slot yields the new value.
-TEST_F(SequenceLocalStorageSlotTest, GetSetMultipleSlots) {
- SequenceLocalStorageSlot<int> slot1;
- SequenceLocalStorageSlot<int> slot2;
- SequenceLocalStorageSlot<int> slot3;
-
- slot1.Set(1);
- slot2.Set(2);
- slot3.Set(3);
-
- EXPECT_EQ(slot1.Get(), 1);
- EXPECT_EQ(slot2.Get(), 2);
- EXPECT_EQ(slot3.Get(), 3);
-
- slot3.Set(4);
- slot2.Set(5);
- slot1.Set(6);
-
- EXPECT_EQ(slot3.Get(), 4);
- EXPECT_EQ(slot2.Get(), 5);
- EXPECT_EQ(slot1.Get(), 6);
-}
-
-// Verify that changing the the value returned by Get() changes the value
-// in sequence local storage.
-TEST_F(SequenceLocalStorageSlotTest, GetReferenceModifiable) {
- SequenceLocalStorageSlot<bool> slot;
- slot.Set(false);
- slot.Get() = true;
- EXPECT_TRUE(slot.Get());
-}
-
-// Verify that a move-only type can be stored in sequence local storage.
-TEST_F(SequenceLocalStorageSlotTest, SetGetWithMoveOnlyType) {
- std::unique_ptr<int> int_unique_ptr = std::make_unique<int>(5);
-
- SequenceLocalStorageSlot<std::unique_ptr<int>> slot;
- slot.Set(std::move(int_unique_ptr));
-
- EXPECT_EQ(*slot.Get(), 5);
-}
-
-// Verify that a Get() without a previous Set() on a slot returns a
-// default-constructed value.
-TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructs) {
- struct DefaultConstructable {
- int x = 0x12345678;
- };
-
- SequenceLocalStorageSlot<DefaultConstructable> slot;
-
- EXPECT_EQ(slot.Get().x, 0x12345678);
-}
-
-// Verify that a Get() without a previous Set() on a slot with a POD-type
-// returns a default-constructed value.
-// Note: this test could be flaky and give a false pass. If it's flaky, the test
-// might've "passed" because the memory for the slot happened to be zeroed.
-TEST_F(SequenceLocalStorageSlotTest, GetWithoutSetDefaultConstructsPOD) {
- SequenceLocalStorageSlot<void*> slot;
-
- EXPECT_EQ(slot.Get(), nullptr);
-}
-
-// Verify that the value of a slot is specific to a SequenceLocalStorageMap
-TEST(SequenceLocalStorageSlotMultipleMapTest, SetGetMultipleMapsOneSlot) {
- SequenceLocalStorageSlot<unsigned int> slot;
- internal::SequenceLocalStorageMap sequence_local_storage_maps[5];
-
- // Set the value of the slot to be the index of the current
- // SequenceLocalStorageMaps in the vector
- for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
- internal::ScopedSetSequenceLocalStorageMapForCurrentThread
- scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
-
- slot.Set(i);
- }
-
- for (unsigned int i = 0; i < arraysize(sequence_local_storage_maps); ++i) {
- internal::ScopedSetSequenceLocalStorageMapForCurrentThread
- scoped_sequence_local_storage(&sequence_local_storage_maps[i]);
-
- EXPECT_EQ(slot.Get(), i);
- }
-}
-
-} // 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 48394da..0000000
--- 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/simple_thread_unittest.cc b/base/threading/simple_thread_unittest.cc
deleted file mode 100644
index 4e618f9..0000000
--- a/base/threading/simple_thread_unittest.cc
+++ /dev/null
@@ -1,234 +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/atomic_sequence_num.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class SetIntRunner : public DelegateSimpleThread::Delegate {
- public:
- SetIntRunner(int* ptr, int val) : ptr_(ptr), val_(val) { }
- ~SetIntRunner() override = default;
-
- private:
- void Run() override { *ptr_ = val_; }
-
- int* ptr_;
- int val_;
-
- DISALLOW_COPY_AND_ASSIGN(SetIntRunner);
-};
-
-// Signals |started_| when Run() is invoked and waits until |released_| is
-// signaled to return, signaling |done_| before doing so. Useful for tests that
-// care to control Run()'s flow.
-class ControlledRunner : public DelegateSimpleThread::Delegate {
- public:
- ControlledRunner()
- : started_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- released_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED),
- done_(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- ~ControlledRunner() override { ReleaseAndWaitUntilDone(); }
-
- void WaitUntilStarted() { started_.Wait(); }
-
- void ReleaseAndWaitUntilDone() {
- released_.Signal();
- done_.Wait();
- }
-
- private:
- void Run() override {
- started_.Signal();
- released_.Wait();
- done_.Signal();
- }
-
- WaitableEvent started_;
- WaitableEvent released_;
- WaitableEvent done_;
-
- DISALLOW_COPY_AND_ASSIGN(ControlledRunner);
-};
-
-class WaitEventRunner : public DelegateSimpleThread::Delegate {
- public:
- explicit WaitEventRunner(WaitableEvent* event) : event_(event) { }
- ~WaitEventRunner() override = default;
-
- private:
- void Run() override {
- EXPECT_FALSE(event_->IsSignaled());
- event_->Signal();
- EXPECT_TRUE(event_->IsSignaled());
- }
-
- WaitableEvent* event_;
-
- DISALLOW_COPY_AND_ASSIGN(WaitEventRunner);
-};
-
-class SeqRunner : public DelegateSimpleThread::Delegate {
- public:
- explicit SeqRunner(AtomicSequenceNumber* seq) : seq_(seq) { }
-
- private:
- void Run() override { seq_->GetNext(); }
-
- AtomicSequenceNumber* seq_;
-
- DISALLOW_COPY_AND_ASSIGN(SeqRunner);
-};
-
-// We count up on a sequence number, firing on the event when we've hit our
-// expected amount, otherwise we wait on the event. This will ensure that we
-// have all threads outstanding until we hit our expected thread pool size.
-class VerifyPoolRunner : public DelegateSimpleThread::Delegate {
- public:
- VerifyPoolRunner(AtomicSequenceNumber* seq,
- int total, WaitableEvent* event)
- : seq_(seq), total_(total), event_(event) { }
-
- private:
- void Run() override {
- if (seq_->GetNext() == total_) {
- event_->Signal();
- } else {
- event_->Wait();
- }
- }
-
- AtomicSequenceNumber* seq_;
- int total_;
- WaitableEvent* event_;
-
- DISALLOW_COPY_AND_ASSIGN(VerifyPoolRunner);
-};
-
-} // namespace
-
-TEST(SimpleThreadTest, CreateAndJoin) {
- int stack_int = 0;
-
- SetIntRunner runner(&stack_int, 7);
- EXPECT_EQ(0, stack_int);
-
- DelegateSimpleThread thread(&runner, "int_setter");
- EXPECT_FALSE(thread.HasBeenStarted());
- EXPECT_FALSE(thread.HasBeenJoined());
- EXPECT_EQ(0, stack_int);
-
- thread.Start();
- EXPECT_TRUE(thread.HasBeenStarted());
- EXPECT_FALSE(thread.HasBeenJoined());
-
- thread.Join();
- EXPECT_TRUE(thread.HasBeenStarted());
- EXPECT_TRUE(thread.HasBeenJoined());
- EXPECT_EQ(7, stack_int);
-}
-
-TEST(SimpleThreadTest, WaitForEvent) {
- // Create a thread, and wait for it to signal us.
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- WaitEventRunner runner(&event);
- DelegateSimpleThread thread(&runner, "event_waiter");
-
- EXPECT_FALSE(event.IsSignaled());
- thread.Start();
- event.Wait();
- EXPECT_TRUE(event.IsSignaled());
- thread.Join();
-}
-
-TEST(SimpleThreadTest, NonJoinableStartAndDieOnJoin) {
- ControlledRunner runner;
-
- SimpleThread::Options options;
- options.joinable = false;
- DelegateSimpleThread thread(&runner, "non_joinable", options);
-
- EXPECT_FALSE(thread.HasBeenStarted());
- thread.Start();
- EXPECT_TRUE(thread.HasBeenStarted());
-
- // Note: this is not quite the same as |thread.HasBeenStarted()| which
- // represents ThreadMain() getting ready to invoke Run() whereas
- // |runner.WaitUntilStarted()| ensures Run() was actually invoked.
- runner.WaitUntilStarted();
-
- EXPECT_FALSE(thread.HasBeenJoined());
- EXPECT_DCHECK_DEATH({ thread.Join(); });
-}
-
-TEST(SimpleThreadTest, NonJoinableInactiveDelegateDestructionIsOkay) {
- std::unique_ptr<ControlledRunner> runner(new ControlledRunner);
-
- SimpleThread::Options options;
- options.joinable = false;
- std::unique_ptr<DelegateSimpleThread> thread(
- new DelegateSimpleThread(runner.get(), "non_joinable", options));
-
- thread->Start();
- runner->WaitUntilStarted();
-
- // Deleting a non-joinable SimpleThread after Run() was invoked is okay.
- thread.reset();
-
- runner->WaitUntilStarted();
- runner->ReleaseAndWaitUntilDone();
- // It should be safe to destroy a Delegate after its Run() method completed.
- runner.reset();
-}
-
-TEST(SimpleThreadTest, ThreadPool) {
- AtomicSequenceNumber seq;
- SeqRunner runner(&seq);
- DelegateSimpleThreadPool pool("seq_runner", 10);
-
- // Add work before we're running.
- pool.AddWork(&runner, 300);
-
- EXPECT_EQ(seq.GetNext(), 0);
- pool.Start();
-
- // Add work while we're running.
- pool.AddWork(&runner, 300);
-
- pool.JoinAll();
-
- EXPECT_EQ(seq.GetNext(), 601);
-
- // We can reuse our pool. Verify that all 10 threads can actually run in
- // parallel, so this test will only pass if there are actually 10 threads.
- AtomicSequenceNumber seq2;
- WaitableEvent event(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- // Changing 9 to 10, for example, would cause us JoinAll() to never return.
- VerifyPoolRunner verifier(&seq2, 9, &event);
- pool.Start();
-
- pool.AddWork(&verifier, 10);
-
- pool.JoinAll();
- EXPECT_EQ(seq2.GetNext(), 10);
-}
-
-} // namespace base
diff --git a/base/threading/thread_checker_unittest.cc b/base/threading/thread_checker_unittest.cc
deleted file mode 100644
index 5fbbc52..0000000
--- a/base/threading/thread_checker_unittest.cc
+++ /dev/null
@@ -1,245 +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/thread_checker.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/bind_helpers.h"
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "base/sequence_token.h"
-#include "base/test/gtest_util.h"
-#include "base/test/test_simple_task_runner.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-// A thread that runs a callback.
-class RunCallbackThread : public SimpleThread {
- public:
- explicit RunCallbackThread(const Closure& callback)
- : SimpleThread("RunCallbackThread"), callback_(callback) {}
-
- private:
- // SimpleThread:
- void Run() override { callback_.Run(); }
-
- const Closure callback_;
-
- DISALLOW_COPY_AND_ASSIGN(RunCallbackThread);
-};
-
-// Runs a callback on a new thread synchronously.
-void RunCallbackOnNewThreadSynchronously(const Closure& callback) {
- RunCallbackThread run_callback_thread(callback);
- run_callback_thread.Start();
- run_callback_thread.Join();
-}
-
-void ExpectCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
- ASSERT_TRUE(thread_checker);
-
- // This should bind |thread_checker| to the current thread if it wasn't
- // already bound to a thread.
- EXPECT_TRUE(thread_checker->CalledOnValidThread());
-
- // Since |thread_checker| is now bound to the current thread, another call to
- // CalledOnValidThread() should return true.
- EXPECT_TRUE(thread_checker->CalledOnValidThread());
-}
-
-void ExpectNotCalledOnValidThread(ThreadCheckerImpl* thread_checker) {
- ASSERT_TRUE(thread_checker);
- EXPECT_FALSE(thread_checker->CalledOnValidThread());
-}
-
-void ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle(
- ThreadCheckerImpl* thread_checker,
- SequenceToken sequence_token) {
- ThreadTaskRunnerHandle thread_task_runner_handle(
- MakeRefCounted<TestSimpleTaskRunner>());
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(sequence_token);
- ExpectNotCalledOnValidThread(thread_checker);
-}
-
-} // namespace
-
-TEST(ThreadCheckerTest, AllowedSameThreadNoSequenceToken) {
- ThreadCheckerImpl thread_checker;
- EXPECT_TRUE(thread_checker.CalledOnValidThread());
-}
-
-TEST(ThreadCheckerTest,
- AllowedSameThreadAndSequenceDifferentTasksWithThreadTaskRunnerHandle) {
- ThreadTaskRunnerHandle thread_task_runner_handle(
- MakeRefCounted<TestSimpleTaskRunner>());
-
- std::unique_ptr<ThreadCheckerImpl> thread_checker;
- const SequenceToken sequence_token = SequenceToken::Create();
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(sequence_token);
- thread_checker.reset(new ThreadCheckerImpl);
- }
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(sequence_token);
- EXPECT_TRUE(thread_checker->CalledOnValidThread());
- }
-}
-
-TEST(ThreadCheckerTest,
- AllowedSameThreadSequenceAndTaskNoThreadTaskRunnerHandle) {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- ThreadCheckerImpl thread_checker;
- EXPECT_TRUE(thread_checker.CalledOnValidThread());
-}
-
-TEST(ThreadCheckerTest,
- DisallowedSameThreadAndSequenceDifferentTasksNoThreadTaskRunnerHandle) {
- std::unique_ptr<ThreadCheckerImpl> thread_checker;
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- thread_checker.reset(new ThreadCheckerImpl);
- }
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- EXPECT_FALSE(thread_checker->CalledOnValidThread());
- }
-}
-
-TEST(ThreadCheckerTest, DisallowedDifferentThreadsNoSequenceToken) {
- ThreadCheckerImpl thread_checker;
- RunCallbackOnNewThreadSynchronously(
- Bind(&ExpectNotCalledOnValidThread, Unretained(&thread_checker)));
-}
-
-TEST(ThreadCheckerTest, DisallowedDifferentThreadsSameSequence) {
- ThreadTaskRunnerHandle thread_task_runner_handle(
- MakeRefCounted<TestSimpleTaskRunner>());
- const SequenceToken sequence_token(SequenceToken::Create());
-
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(sequence_token);
- ThreadCheckerImpl thread_checker;
- EXPECT_TRUE(thread_checker.CalledOnValidThread());
-
- RunCallbackOnNewThreadSynchronously(Bind(
- &ExpectNotCalledOnValidThreadWithSequenceTokenAndThreadTaskRunnerHandle,
- Unretained(&thread_checker), sequence_token));
-}
-
-TEST(ThreadCheckerTest, DisallowedSameThreadDifferentSequence) {
- std::unique_ptr<ThreadCheckerImpl> thread_checker;
-
- ThreadTaskRunnerHandle thread_task_runner_handle(
- MakeRefCounted<TestSimpleTaskRunner>());
-
- {
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- thread_checker.reset(new ThreadCheckerImpl);
- }
-
- {
- // Different SequenceToken.
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- EXPECT_FALSE(thread_checker->CalledOnValidThread());
- }
-
- // No SequenceToken.
- EXPECT_FALSE(thread_checker->CalledOnValidThread());
-}
-
-TEST(ThreadCheckerTest, DetachFromThread) {
- ThreadCheckerImpl thread_checker;
- thread_checker.DetachFromThread();
-
- // Verify that CalledOnValidThread() returns true when called on a different
- // thread after a call to DetachFromThread().
- RunCallbackOnNewThreadSynchronously(
- Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
-
- EXPECT_FALSE(thread_checker.CalledOnValidThread());
-}
-
-TEST(ThreadCheckerTest, DetachFromThreadWithSequenceToken) {
- ThreadTaskRunnerHandle thread_task_runner_handle(
- MakeRefCounted<TestSimpleTaskRunner>());
- ScopedSetSequenceTokenForCurrentThread
- scoped_set_sequence_token_for_current_thread(SequenceToken::Create());
- ThreadCheckerImpl thread_checker;
- thread_checker.DetachFromThread();
-
- // Verify that CalledOnValidThread() returns true when called on a different
- // thread after a call to DetachFromThread().
- RunCallbackOnNewThreadSynchronously(
- Bind(&ExpectCalledOnValidThread, Unretained(&thread_checker)));
-
- EXPECT_FALSE(thread_checker.CalledOnValidThread());
-}
-
-namespace {
-
-// This fixture is a helper for unit testing the thread checker macros as it is
-// not possible to inline ExpectDeathOnOtherThread() and
-// ExpectNoDeathOnOtherThreadAfterDetach() as lambdas since binding
-// |Unretained(&my_sequence_checker)| wouldn't compile on non-dcheck builds
-// where it won't be defined.
-class ThreadCheckerMacroTest : public testing::Test {
- public:
- ThreadCheckerMacroTest() = default;
-
- void ExpectDeathOnOtherThread() {
-#if DCHECK_IS_ON()
- EXPECT_DCHECK_DEATH({ DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_); });
-#else
- // Happily no-ops on non-dcheck builds.
- DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
-#endif
- }
-
- void ExpectNoDeathOnOtherThreadAfterDetach() {
- DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_);
- DCHECK_CALLED_ON_VALID_THREAD(my_thread_checker_)
- << "Make sure it compiles when DCHECK is off";
- }
-
- protected:
- THREAD_CHECKER(my_thread_checker_);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ThreadCheckerMacroTest);
-};
-
-} // namespace
-
-TEST_F(ThreadCheckerMacroTest, Macros) {
- THREAD_CHECKER(my_thread_checker);
-
- RunCallbackOnNewThreadSynchronously(Bind(
- &ThreadCheckerMacroTest::ExpectDeathOnOtherThread, Unretained(this)));
-
- DETACH_FROM_THREAD(my_thread_checker_);
-
- RunCallbackOnNewThreadSynchronously(
- Bind(&ThreadCheckerMacroTest::ExpectNoDeathOnOtherThreadAfterDetach,
- Unretained(this)));
-}
-
-} // namespace base
diff --git a/base/threading/thread_collision_warner_unittest.cc b/base/threading/thread_collision_warner_unittest.cc
deleted file mode 100644
index cd56768..0000000
--- a/base/threading/thread_collision_warner_unittest.cc
+++ /dev/null
@@ -1,382 +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/thread_collision_warner.h"
-
-#include <memory>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/simple_thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-// '' : local class member function does not have a body
-MSVC_PUSH_DISABLE_WARNING(4822)
-
-
-#if defined(NDEBUG)
-
-// Would cause a memory leak otherwise.
-#undef DFAKE_MUTEX
-#define DFAKE_MUTEX(obj) std::unique_ptr<base::AsserterBase> obj
-
-// In Release, we expect the AsserterBase::warn() to not happen.
-#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_FALSE
-
-#else
-
-// In Debug, we expect the AsserterBase::warn() to happen.
-#define EXPECT_NDEBUG_FALSE_DEBUG_TRUE EXPECT_TRUE
-
-#endif
-
-
-namespace {
-
-// This is the asserter used with ThreadCollisionWarner instead of the default
-// DCheckAsserter. The method fail_state is used to know if a collision took
-// place.
-class AssertReporter : public base::AsserterBase {
- public:
- AssertReporter()
- : failed_(false) {}
-
- void warn() override { failed_ = true; }
-
- ~AssertReporter() override = default;
-
- bool fail_state() const { return failed_; }
- void reset() { failed_ = false; }
-
- private:
- bool failed_;
-};
-
-} // namespace
-
-TEST(ThreadCollisionTest, BookCriticalSection) {
- AssertReporter* local_reporter = new AssertReporter();
-
- base::ThreadCollisionWarner warner(local_reporter);
- EXPECT_FALSE(local_reporter->fail_state());
-
- { // Pin section.
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- { // Pin section.
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- }
- }
-}
-
-TEST(ThreadCollisionTest, ScopedRecursiveBookCriticalSection) {
- AssertReporter* local_reporter = new AssertReporter();
-
- base::ThreadCollisionWarner warner(local_reporter);
- EXPECT_FALSE(local_reporter->fail_state());
-
- { // Pin section.
- DFAKE_SCOPED_RECURSIVE_LOCK(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- { // Pin section again (allowed by DFAKE_SCOPED_RECURSIVE_LOCK)
- DFAKE_SCOPED_RECURSIVE_LOCK(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- } // Unpin section.
- } // Unpin section.
-
- // Check that section is not pinned
- { // Pin section.
- DFAKE_SCOPED_LOCK(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- } // Unpin section.
-}
-
-TEST(ThreadCollisionTest, ScopedBookCriticalSection) {
- AssertReporter* local_reporter = new AssertReporter();
-
- base::ThreadCollisionWarner warner(local_reporter);
- EXPECT_FALSE(local_reporter->fail_state());
-
- { // Pin section.
- DFAKE_SCOPED_LOCK(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- } // Unpin section.
-
- { // Pin section.
- DFAKE_SCOPED_LOCK(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- {
- // Pin section again (not allowed by DFAKE_SCOPED_LOCK)
- DFAKE_SCOPED_LOCK(warner);
- EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
- // Reset the status of warner for further tests.
- local_reporter->reset();
- } // Unpin section.
- } // Unpin section.
-
- {
- // Pin section.
- DFAKE_SCOPED_LOCK(warner);
- EXPECT_FALSE(local_reporter->fail_state());
- } // Unpin section.
-}
-
-TEST(ThreadCollisionTest, MTBookCriticalSectionTest) {
- class NonThreadSafeQueue {
- public:
- explicit NonThreadSafeQueue(base::AsserterBase* asserter)
- : push_pop_(asserter) {
- }
-
- void push(int value) {
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
- }
-
- int pop() {
- DFAKE_SCOPED_LOCK_THREAD_LOCKED(push_pop_);
- return 0;
- }
-
- private:
- DFAKE_MUTEX(push_pop_);
-
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
- };
-
- class QueueUser : public base::DelegateSimpleThread::Delegate {
- public:
- explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
-
- void Run() override {
- queue_->push(0);
- queue_->pop();
- }
-
- private:
- NonThreadSafeQueue* queue_;
- };
-
- AssertReporter* local_reporter = new AssertReporter();
-
- NonThreadSafeQueue queue(local_reporter);
-
- QueueUser queue_user_a(&queue);
- QueueUser queue_user_b(&queue);
-
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
-
- thread_a.Start();
- thread_b.Start();
-
- thread_a.Join();
- thread_b.Join();
-
- EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
-}
-
-TEST(ThreadCollisionTest, MTScopedBookCriticalSectionTest) {
- // Queue with a 5 seconds push execution time, hopefuly the two used threads
- // in the test will enter the push at same time.
- class NonThreadSafeQueue {
- public:
- explicit NonThreadSafeQueue(base::AsserterBase* asserter)
- : push_pop_(asserter) {
- }
-
- void push(int value) {
- DFAKE_SCOPED_LOCK(push_pop_);
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(5));
- }
-
- int pop() {
- DFAKE_SCOPED_LOCK(push_pop_);
- return 0;
- }
-
- private:
- DFAKE_MUTEX(push_pop_);
-
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
- };
-
- class QueueUser : public base::DelegateSimpleThread::Delegate {
- public:
- explicit QueueUser(NonThreadSafeQueue* queue) : queue_(queue) {}
-
- void Run() override {
- queue_->push(0);
- queue_->pop();
- }
-
- private:
- NonThreadSafeQueue* queue_;
- };
-
- AssertReporter* local_reporter = new AssertReporter();
-
- NonThreadSafeQueue queue(local_reporter);
-
- QueueUser queue_user_a(&queue);
- QueueUser queue_user_b(&queue);
-
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
-
- thread_a.Start();
- thread_b.Start();
-
- thread_a.Join();
- thread_b.Join();
-
- EXPECT_NDEBUG_FALSE_DEBUG_TRUE(local_reporter->fail_state());
-}
-
-TEST(ThreadCollisionTest, MTSynchedScopedBookCriticalSectionTest) {
- // Queue with a 2 seconds push execution time, hopefuly the two used threads
- // in the test will enter the push at same time.
- class NonThreadSafeQueue {
- public:
- explicit NonThreadSafeQueue(base::AsserterBase* asserter)
- : push_pop_(asserter) {
- }
-
- void push(int value) {
- DFAKE_SCOPED_LOCK(push_pop_);
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
- }
-
- int pop() {
- DFAKE_SCOPED_LOCK(push_pop_);
- return 0;
- }
-
- private:
- DFAKE_MUTEX(push_pop_);
-
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
- };
-
- // This time the QueueUser class protects the non thread safe queue with
- // a lock.
- class QueueUser : public base::DelegateSimpleThread::Delegate {
- public:
- QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
- : queue_(queue), lock_(lock) {}
-
- void Run() override {
- {
- base::AutoLock auto_lock(*lock_);
- queue_->push(0);
- }
- {
- base::AutoLock auto_lock(*lock_);
- queue_->pop();
- }
- }
- private:
- NonThreadSafeQueue* queue_;
- base::Lock* lock_;
- };
-
- AssertReporter* local_reporter = new AssertReporter();
-
- NonThreadSafeQueue queue(local_reporter);
-
- base::Lock lock;
-
- QueueUser queue_user_a(&queue, &lock);
- QueueUser queue_user_b(&queue, &lock);
-
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
-
- thread_a.Start();
- thread_b.Start();
-
- thread_a.Join();
- thread_b.Join();
-
- EXPECT_FALSE(local_reporter->fail_state());
-}
-
-TEST(ThreadCollisionTest, MTSynchedScopedRecursiveBookCriticalSectionTest) {
- // Queue with a 2 seconds push execution time, hopefuly the two used threads
- // in the test will enter the push at same time.
- class NonThreadSafeQueue {
- public:
- explicit NonThreadSafeQueue(base::AsserterBase* asserter)
- : push_pop_(asserter) {
- }
-
- void push(int) {
- DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
- bar();
- base::PlatformThread::Sleep(base::TimeDelta::FromSeconds(2));
- }
-
- int pop() {
- DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
- return 0;
- }
-
- void bar() {
- DFAKE_SCOPED_RECURSIVE_LOCK(push_pop_);
- }
-
- private:
- DFAKE_MUTEX(push_pop_);
-
- DISALLOW_COPY_AND_ASSIGN(NonThreadSafeQueue);
- };
-
- // This time the QueueUser class protects the non thread safe queue with
- // a lock.
- class QueueUser : public base::DelegateSimpleThread::Delegate {
- public:
- QueueUser(NonThreadSafeQueue* queue, base::Lock* lock)
- : queue_(queue), lock_(lock) {}
-
- void Run() override {
- {
- base::AutoLock auto_lock(*lock_);
- queue_->push(0);
- }
- {
- base::AutoLock auto_lock(*lock_);
- queue_->bar();
- }
- {
- base::AutoLock auto_lock(*lock_);
- queue_->pop();
- }
- }
- private:
- NonThreadSafeQueue* queue_;
- base::Lock* lock_;
- };
-
- AssertReporter* local_reporter = new AssertReporter();
-
- NonThreadSafeQueue queue(local_reporter);
-
- base::Lock lock;
-
- QueueUser queue_user_a(&queue, &lock);
- QueueUser queue_user_b(&queue, &lock);
-
- base::DelegateSimpleThread thread_a(&queue_user_a, "queue_user_thread_a");
- base::DelegateSimpleThread thread_b(&queue_user_b, "queue_user_thread_b");
-
- thread_a.Start();
- thread_b.Start();
-
- thread_a.Join();
- thread_b.Join();
-
- EXPECT_FALSE(local_reporter->fail_state());
-}
diff --git a/base/threading/thread_id_name_manager_unittest.cc b/base/threading/thread_id_name_manager_unittest.cc
deleted file mode 100644
index 350dc0f..0000000
--- a/base/threading/thread_id_name_manager_unittest.cc
+++ /dev/null
@@ -1,93 +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/thread_id_name_manager.h"
-
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-typedef PlatformTest ThreadIdNameManagerTest;
-
-namespace {
-
-const char kAThread[] = "a thread";
-const char kBThread[] = "b thread";
-
-TEST_F(ThreadIdNameManagerTest, AddThreads) {
- base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
- base::Thread thread_a(kAThread);
- base::Thread thread_b(kBThread);
-
- thread_a.StartAndWaitForTesting();
- thread_b.StartAndWaitForTesting();
-
- EXPECT_STREQ(kAThread, manager->GetName(thread_a.GetThreadId()));
- EXPECT_STREQ(kBThread, manager->GetName(thread_b.GetThreadId()));
-
- thread_b.Stop();
- thread_a.Stop();
-}
-
-TEST_F(ThreadIdNameManagerTest, RemoveThreads) {
- base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
- base::Thread thread_a(kAThread);
-
- thread_a.StartAndWaitForTesting();
- {
- base::Thread thread_b(kBThread);
- thread_b.StartAndWaitForTesting();
- thread_b.Stop();
- }
- EXPECT_STREQ(kAThread, manager->GetName(thread_a.GetThreadId()));
-
- thread_a.Stop();
- EXPECT_STREQ("", manager->GetName(thread_a.GetThreadId()));
-}
-
-TEST_F(ThreadIdNameManagerTest, RestartThread) {
- base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
- base::Thread thread_a(kAThread);
-
- thread_a.StartAndWaitForTesting();
- base::PlatformThreadId a_id = thread_a.GetThreadId();
- EXPECT_STREQ(kAThread, manager->GetName(a_id));
- thread_a.Stop();
-
- thread_a.StartAndWaitForTesting();
- EXPECT_STREQ("", manager->GetName(a_id));
- EXPECT_STREQ(kAThread, manager->GetName(thread_a.GetThreadId()));
- thread_a.Stop();
-}
-
-TEST_F(ThreadIdNameManagerTest, ThreadNameInterning) {
- base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
-
- base::PlatformThreadId a_id = base::PlatformThread::CurrentId();
- base::PlatformThread::SetName("First Name");
- std::string version = manager->GetName(a_id);
-
- base::PlatformThread::SetName("New name");
- EXPECT_NE(version, manager->GetName(a_id));
- base::PlatformThread::SetName("");
-}
-
-TEST_F(ThreadIdNameManagerTest, ResettingNameKeepsCorrectInternedValue) {
- base::ThreadIdNameManager* manager = base::ThreadIdNameManager::GetInstance();
-
- base::PlatformThreadId a_id = base::PlatformThread::CurrentId();
- base::PlatformThread::SetName("Test Name");
- std::string version = manager->GetName(a_id);
-
- base::PlatformThread::SetName("New name");
- EXPECT_NE(version, manager->GetName(a_id));
-
- base::PlatformThread::SetName("Test Name");
- EXPECT_EQ(version, manager->GetName(a_id));
-
- base::PlatformThread::SetName("");
-}
-
-} // namespace
diff --git a/base/threading/thread_local_storage_unittest.cc b/base/threading/thread_local_storage_unittest.cc
deleted file mode 100644
index 006f928..0000000
--- a/base/threading/thread_local_storage_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/threading/thread_local_storage.h"
-
-#if defined(OS_WIN)
-#include <windows.h>
-#include <process.h>
-#endif
-
-#include "base/macros.h"
-#include "base/no_destructor.h"
-#include "base/threading/simple_thread.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_WIN)
-// Ignore warnings about ptr->int conversions that we use when
-// storing ints into ThreadLocalStorage.
-#pragma warning(disable : 4311 4312)
-#endif
-
-namespace base {
-
-#if defined(OS_POSIX)
-
-namespace internal {
-
-// This class is friended by ThreadLocalStorage.
-class ThreadLocalStorageTestInternal {
- public:
- static bool HasBeenDestroyed() {
- return ThreadLocalStorage::HasBeenDestroyed();
- }
-};
-
-} // namespace internal
-
-#endif // defined(OS_POSIX)
-
-namespace {
-
-const int kInitialTlsValue = 0x5555;
-const int kFinalTlsValue = 0x7777;
-// How many times must a destructor be called before we really are done.
-const int kNumberDestructorCallRepetitions = 3;
-
-void ThreadLocalStorageCleanup(void* value);
-
-ThreadLocalStorage::Slot& TLSSlot() {
- static NoDestructor<ThreadLocalStorage::Slot> slot(
- &ThreadLocalStorageCleanup);
- return *slot;
-}
-
-class ThreadLocalStorageRunner : public DelegateSimpleThread::Delegate {
- public:
- explicit ThreadLocalStorageRunner(int* tls_value_ptr)
- : tls_value_ptr_(tls_value_ptr) {}
-
- ~ThreadLocalStorageRunner() override = default;
-
- void Run() override {
- *tls_value_ptr_ = kInitialTlsValue;
- TLSSlot().Set(tls_value_ptr_);
-
- int* ptr = static_cast<int*>(TLSSlot().Get());
- EXPECT_EQ(ptr, tls_value_ptr_);
- EXPECT_EQ(*ptr, kInitialTlsValue);
- *tls_value_ptr_ = 0;
-
- ptr = static_cast<int*>(TLSSlot().Get());
- EXPECT_EQ(ptr, tls_value_ptr_);
- EXPECT_EQ(*ptr, 0);
-
- *ptr = kFinalTlsValue + kNumberDestructorCallRepetitions;
- }
-
- private:
- int* tls_value_ptr_;
- DISALLOW_COPY_AND_ASSIGN(ThreadLocalStorageRunner);
-};
-
-
-void ThreadLocalStorageCleanup(void *value) {
- int *ptr = reinterpret_cast<int*>(value);
- // Destructors should never be called with a NULL.
- ASSERT_NE(reinterpret_cast<int*>(NULL), ptr);
- if (*ptr == kFinalTlsValue)
- return; // We've been called enough times.
- ASSERT_LT(kFinalTlsValue, *ptr);
- ASSERT_GE(kFinalTlsValue + kNumberDestructorCallRepetitions, *ptr);
- --*ptr; // Move closer to our target.
- // Tell tls that we're not done with this thread, and still need destruction.
- TLSSlot().Set(value);
-}
-
-#if defined(OS_POSIX)
-constexpr intptr_t kDummyValue = 0xABCD;
-constexpr size_t kKeyCount = 20;
-
-// The order in which pthread keys are destructed is not specified by the POSIX
-// specification. Hopefully, of the 20 keys we create, some of them should be
-// destroyed after the TLS key is destroyed.
-class UseTLSDuringDestructionRunner {
- public:
- UseTLSDuringDestructionRunner() = default;
-
- // The order in which pthread_key destructors are called is not well defined.
- // Hopefully, by creating 10 both before and after initializing TLS on the
- // thread, at least 1 will be called after TLS destruction.
- void Run() {
- ASSERT_FALSE(internal::ThreadLocalStorageTestInternal::HasBeenDestroyed());
-
- // Create 10 pthread keys before initializing TLS on the thread.
- size_t slot_index = 0;
- for (; slot_index < 10; ++slot_index) {
- CreateTlsKeyWithDestructor(slot_index);
- }
-
- // Initialize the Chrome TLS system. It's possible that base::Thread has
- // already initialized Chrome TLS, but we don't rely on that.
- slot_.Set(reinterpret_cast<void*>(kDummyValue));
-
- // Create 10 pthread keys after initializing TLS on the thread.
- for (; slot_index < kKeyCount; ++slot_index) {
- CreateTlsKeyWithDestructor(slot_index);
- }
- }
-
- bool teardown_works_correctly() { return teardown_works_correctly_; }
-
- private:
- struct TLSState {
- pthread_key_t key;
- bool* teardown_works_correctly;
- };
-
- // The POSIX TLS destruction API takes as input a single C-function, which is
- // called with the current |value| of a (key, value) pair. We need this
- // function to do two things: set the |value| to nullptr, which requires
- // knowing the associated |key|, and update the |teardown_works_correctly_|
- // state.
- //
- // To accomplish this, we set the value to an instance of TLSState, which
- // contains |key| as well as a pointer to |teardown_works_correctly|.
- static void ThreadLocalDestructor(void* value) {
- TLSState* state = static_cast<TLSState*>(value);
- int result = pthread_setspecific(state->key, nullptr);
- ASSERT_EQ(result, 0);
-
- // If this path is hit, then the thread local destructor was called after
- // the Chrome-TLS destructor and the internal state was updated correctly.
- // No further checks are necessary.
- if (internal::ThreadLocalStorageTestInternal::HasBeenDestroyed()) {
- *(state->teardown_works_correctly) = true;
- return;
- }
-
- // If this path is hit, then the thread local destructor was called before
- // the Chrome-TLS destructor is hit. The ThreadLocalStorage::Slot should
- // still function correctly.
- ASSERT_EQ(reinterpret_cast<intptr_t>(slot_.Get()), kDummyValue);
- }
-
- void CreateTlsKeyWithDestructor(size_t index) {
- ASSERT_LT(index, kKeyCount);
-
- tls_states_[index].teardown_works_correctly = &teardown_works_correctly_;
- int result = pthread_key_create(
- &(tls_states_[index].key),
- UseTLSDuringDestructionRunner::ThreadLocalDestructor);
- ASSERT_EQ(result, 0);
-
- result = pthread_setspecific(tls_states_[index].key, &tls_states_[index]);
- ASSERT_EQ(result, 0);
- }
-
- static base::ThreadLocalStorage::Slot slot_;
- bool teardown_works_correctly_ = false;
- TLSState tls_states_[kKeyCount];
-
- DISALLOW_COPY_AND_ASSIGN(UseTLSDuringDestructionRunner);
-};
-
-base::ThreadLocalStorage::Slot UseTLSDuringDestructionRunner::slot_;
-
-void* UseTLSTestThreadRun(void* input) {
- UseTLSDuringDestructionRunner* runner =
- static_cast<UseTLSDuringDestructionRunner*>(input);
- runner->Run();
- return nullptr;
-}
-
-#endif // defined(OS_POSIX)
-
-} // namespace
-
-TEST(ThreadLocalStorageTest, Basics) {
- ThreadLocalStorage::Slot slot;
- slot.Set(reinterpret_cast<void*>(123));
- int value = reinterpret_cast<intptr_t>(slot.Get());
- EXPECT_EQ(value, 123);
-}
-
-#if defined(THREAD_SANITIZER) || \
- (defined(OS_WIN) && defined(ARCH_CPU_X86_64) && !defined(NDEBUG))
-// Do not run the test under ThreadSanitizer. Because this test iterates its
-// own TSD destructor for the maximum possible number of times, TSan can't jump
-// in after the last destructor invocation, therefore the destructor remains
-// unsynchronized with the following users of the same TSD slot. This results
-// in race reports between the destructor and functions in other tests.
-//
-// It is disabled on Win x64 with incremental linking (i.e. "Debug") pending
-// resolution of http://crbug.com/251251.
-#define MAYBE_TLSDestructors DISABLED_TLSDestructors
-#else
-#define MAYBE_TLSDestructors TLSDestructors
-#endif
-TEST(ThreadLocalStorageTest, MAYBE_TLSDestructors) {
- // Create a TLS index with a destructor. Create a set of
- // threads that set the TLS, while the destructor cleans it up.
- // After the threads finish, verify that the value is cleaned up.
- const int kNumThreads = 5;
- int values[kNumThreads];
- ThreadLocalStorageRunner* thread_delegates[kNumThreads];
- DelegateSimpleThread* threads[kNumThreads];
-
- // Spawn the threads.
- for (int index = 0; index < kNumThreads; index++) {
- values[index] = kInitialTlsValue;
- thread_delegates[index] = new ThreadLocalStorageRunner(&values[index]);
- threads[index] = new DelegateSimpleThread(thread_delegates[index],
- "tls thread");
- threads[index]->Start();
- }
-
- // Wait for the threads to finish.
- for (int index = 0; index < kNumThreads; index++) {
- threads[index]->Join();
- delete threads[index];
- delete thread_delegates[index];
-
- // Verify that the destructor was called and that we reset.
- EXPECT_EQ(values[index], kFinalTlsValue);
- }
-}
-
-TEST(ThreadLocalStorageTest, TLSReclaim) {
- // Creates and destroys many TLS slots and ensures they all zero-inited.
- for (int i = 0; i < 1000; ++i) {
- ThreadLocalStorage::Slot slot(nullptr);
- EXPECT_EQ(nullptr, slot.Get());
- slot.Set(reinterpret_cast<void*>(0xBAADF00D));
- EXPECT_EQ(reinterpret_cast<void*>(0xBAADF00D), slot.Get());
- }
-}
-
-#if defined(OS_POSIX)
-// Unlike POSIX, Windows does not iterate through the OS TLS to cleanup any
-// values there. Instead a per-module thread destruction function is called.
-// However, it is not possible to perform a check after this point (as the code
-// is detached from the thread), so this check remains POSIX only.
-TEST(ThreadLocalStorageTest, UseTLSDuringDestruction) {
- UseTLSDuringDestructionRunner runner;
- pthread_t thread;
- int result = pthread_create(&thread, nullptr, UseTLSTestThreadRun, &runner);
- ASSERT_EQ(result, 0);
-
- result = pthread_join(thread, nullptr);
- ASSERT_EQ(result, 0);
-
- EXPECT_TRUE(runner.teardown_works_correctly());
-}
-#endif // defined(OS_POSIX)
-
-} // namespace base
diff --git a/base/threading/thread_local_unittest.cc b/base/threading/thread_local_unittest.cc
deleted file mode 100644
index 54f2ad2..0000000
--- a/base/threading/thread_local_unittest.cc
+++ /dev/null
@@ -1,164 +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/logging.h"
-#include "base/threading/simple_thread.h"
-#include "base/threading/thread_local.h"
-#include "base/synchronization/waitable_event.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class ThreadLocalTesterBase : public base::DelegateSimpleThreadPool::Delegate {
- public:
- typedef base::ThreadLocalPointer<char> TLPType;
-
- ThreadLocalTesterBase(TLPType* tlp, base::WaitableEvent* done)
- : tlp_(tlp),
- done_(done) {
- }
- ~ThreadLocalTesterBase() override = default;
-
- protected:
- TLPType* tlp_;
- base::WaitableEvent* done_;
-};
-
-class SetThreadLocal : public ThreadLocalTesterBase {
- public:
- SetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
- : ThreadLocalTesterBase(tlp, done), val_(nullptr) {}
- ~SetThreadLocal() override = default;
-
- void set_value(char* val) { val_ = val; }
-
- void Run() override {
- DCHECK(!done_->IsSignaled());
- tlp_->Set(val_);
- done_->Signal();
- }
-
- private:
- char* val_;
-};
-
-class GetThreadLocal : public ThreadLocalTesterBase {
- public:
- GetThreadLocal(TLPType* tlp, base::WaitableEvent* done)
- : ThreadLocalTesterBase(tlp, done), ptr_(nullptr) {}
- ~GetThreadLocal() override = default;
-
- void set_ptr(char** ptr) { ptr_ = ptr; }
-
- void Run() override {
- DCHECK(!done_->IsSignaled());
- *ptr_ = tlp_->Get();
- done_->Signal();
- }
-
- private:
- char** ptr_;
-};
-
-} // namespace
-
-// In this test, we start 2 threads which will access a ThreadLocalPointer. We
-// make sure the default is NULL, and the pointers are unique to the threads.
-TEST(ThreadLocalTest, Pointer) {
- base::DelegateSimpleThreadPool tp1("ThreadLocalTest tp1", 1);
- base::DelegateSimpleThreadPool tp2("ThreadLocalTest tp1", 1);
- tp1.Start();
- tp2.Start();
-
- base::ThreadLocalPointer<char> tlp;
-
- static char* const kBogusPointer = reinterpret_cast<char*>(0x1234);
-
- char* tls_val;
- base::WaitableEvent done(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
-
- GetThreadLocal getter(&tlp, &done);
- getter.set_ptr(&tls_val);
-
- // Check that both threads defaulted to NULL.
- tls_val = kBogusPointer;
- done.Reset();
- tp1.AddWork(&getter);
- done.Wait();
- EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
-
- tls_val = kBogusPointer;
- done.Reset();
- tp2.AddWork(&getter);
- done.Wait();
- EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
-
- SetThreadLocal setter(&tlp, &done);
- setter.set_value(kBogusPointer);
-
- // Have thread 1 set their pointer value to kBogusPointer.
- done.Reset();
- tp1.AddWork(&setter);
- done.Wait();
-
- tls_val = nullptr;
- done.Reset();
- tp1.AddWork(&getter);
- done.Wait();
- EXPECT_EQ(kBogusPointer, tls_val);
-
- // Make sure thread 2 is still NULL
- tls_val = kBogusPointer;
- done.Reset();
- tp2.AddWork(&getter);
- done.Wait();
- EXPECT_EQ(static_cast<char*>(nullptr), tls_val);
-
- // Set thread 2 to kBogusPointer + 1.
- setter.set_value(kBogusPointer + 1);
-
- done.Reset();
- tp2.AddWork(&setter);
- done.Wait();
-
- tls_val = nullptr;
- done.Reset();
- tp2.AddWork(&getter);
- done.Wait();
- EXPECT_EQ(kBogusPointer + 1, tls_val);
-
- // Make sure thread 1 is still kBogusPointer.
- tls_val = nullptr;
- done.Reset();
- tp1.AddWork(&getter);
- done.Wait();
- EXPECT_EQ(kBogusPointer, tls_val);
-
- tp1.JoinAll();
- tp2.JoinAll();
-}
-
-TEST(ThreadLocalTest, Boolean) {
- {
- base::ThreadLocalBoolean tlb;
- EXPECT_FALSE(tlb.Get());
-
- tlb.Set(false);
- EXPECT_FALSE(tlb.Get());
-
- tlb.Set(true);
- EXPECT_TRUE(tlb.Get());
- }
-
- // Our slot should have been freed, we're all reset.
- {
- base::ThreadLocalBoolean tlb;
- EXPECT_FALSE(tlb.Get());
- }
-}
-
-} // namespace base
diff --git a/base/threading/thread_restrictions_unittest.cc b/base/threading/thread_restrictions_unittest.cc
deleted file mode 100644
index a957a9a..0000000
--- a/base/threading/thread_restrictions_unittest.cc
+++ /dev/null
@@ -1,137 +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_restrictions.h"
-
-#include <utility>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/macros.h"
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-class ThreadRestrictionsTest : public testing::Test {
- public:
- ThreadRestrictionsTest() = default;
- ~ThreadRestrictionsTest() override {
- internal::ResetThreadRestrictionsForTesting();
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(ThreadRestrictionsTest);
-};
-
-} // namespace
-
-TEST_F(ThreadRestrictionsTest, BlockingAllowedByDefault) {
- AssertBlockingAllowed();
-}
-
-TEST_F(ThreadRestrictionsTest, ScopedDisallowBlocking) {
- {
- ScopedDisallowBlocking scoped_disallow_blocking;
- EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); });
- }
- AssertBlockingAllowed();
-}
-
-TEST_F(ThreadRestrictionsTest, ScopedAllowBlocking) {
- ScopedDisallowBlocking scoped_disallow_blocking;
- {
- ScopedAllowBlocking scoped_allow_blocking;
- AssertBlockingAllowed();
- }
- EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); });
-}
-
-TEST_F(ThreadRestrictionsTest, ScopedAllowBlockingForTesting) {
- ScopedDisallowBlocking scoped_disallow_blocking;
- {
- ScopedAllowBlockingForTesting scoped_allow_blocking_for_testing;
- AssertBlockingAllowed();
- }
- EXPECT_DCHECK_DEATH({ AssertBlockingAllowed(); });
-}
-
-TEST_F(ThreadRestrictionsTest, BaseSyncPrimitivesAllowedByDefault) {}
-
-TEST_F(ThreadRestrictionsTest, DisallowBaseSyncPrimitives) {
- DisallowBaseSyncPrimitives();
- EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
-}
-
-TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitives) {
- DisallowBaseSyncPrimitives();
- ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives;
- internal::AssertBaseSyncPrimitivesAllowed();
-}
-
-TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitivesResetsState) {
- DisallowBaseSyncPrimitives();
- { ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives; }
- EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
-}
-
-TEST_F(ThreadRestrictionsTest,
- ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed) {
- ScopedDisallowBlocking scoped_disallow_blocking;
- DisallowBaseSyncPrimitives();
-
- // This should DCHECK because blocking is not allowed in this scope
- // and OutsideBlockingScope is not passed to the constructor.
- EXPECT_DCHECK_DEATH(
- { ScopedAllowBaseSyncPrimitives scoped_allow_base_sync_primitives; });
-}
-
-TEST_F(ThreadRestrictionsTest,
- ScopedAllowBaseSyncPrimitivesOutsideBlockingScope) {
- ScopedDisallowBlocking scoped_disallow_blocking;
- DisallowBaseSyncPrimitives();
- ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
- scoped_allow_base_sync_primitives;
- internal::AssertBaseSyncPrimitivesAllowed();
-}
-
-TEST_F(ThreadRestrictionsTest,
- ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState) {
- DisallowBaseSyncPrimitives();
- {
- ScopedAllowBaseSyncPrimitivesOutsideBlockingScope
- scoped_allow_base_sync_primitives;
- }
- EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
-}
-
-TEST_F(ThreadRestrictionsTest, ScopedAllowBaseSyncPrimitivesForTesting) {
- DisallowBaseSyncPrimitives();
- ScopedAllowBaseSyncPrimitivesForTesting
- scoped_allow_base_sync_primitives_for_testing;
- internal::AssertBaseSyncPrimitivesAllowed();
-}
-
-TEST_F(ThreadRestrictionsTest,
- ScopedAllowBaseSyncPrimitivesForTestingResetsState) {
- DisallowBaseSyncPrimitives();
- {
- ScopedAllowBaseSyncPrimitivesForTesting
- scoped_allow_base_sync_primitives_for_testing;
- }
- EXPECT_DCHECK_DEATH({ internal::AssertBaseSyncPrimitivesAllowed(); });
-}
-
-TEST_F(ThreadRestrictionsTest,
- ScopedAllowBaseSyncPrimitivesForTestingWithBlockingDisallowed) {
- ScopedDisallowBlocking scoped_disallow_blocking;
- DisallowBaseSyncPrimitives();
- // This should not DCHECK.
- ScopedAllowBaseSyncPrimitivesForTesting
- scoped_allow_base_sync_primitives_for_testing;
-}
-
-} // 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 1aa02d1..0000000
--- 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/thread_unittest.cc b/base/threading/thread_unittest.cc
deleted file mode 100644
index a1a9ed3..0000000
--- a/base/threading/thread_unittest.cc
+++ /dev/null
@@ -1,579 +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/thread.h"
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include <utility>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/debug/leak_annotations.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
-#include "base/message_loop/message_loop_current.h"
-#include "base/run_loop.h"
-#include "base/single_thread_task_runner.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/test/gtest_util.h"
-#include "base/third_party/dynamic_annotations/dynamic_annotations.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-
-using base::Thread;
-
-typedef PlatformTest ThreadTest;
-
-namespace {
-
-void ToggleValue(bool* value) {
- ANNOTATE_BENIGN_RACE(value, "Test-only data race on boolean "
- "in base/thread_unittest");
- *value = !*value;
-}
-
-class SleepInsideInitThread : public Thread {
- public:
- SleepInsideInitThread() : Thread("none") {
- init_called_ = false;
- ANNOTATE_BENIGN_RACE(
- this, "Benign test-only data race on vptr - http://crbug.com/98219");
- }
- ~SleepInsideInitThread() override { Stop(); }
-
- void Init() override {
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(500));
- init_called_ = true;
- }
- bool InitCalled() { return init_called_; }
-
- private:
- bool init_called_;
-
- DISALLOW_COPY_AND_ASSIGN(SleepInsideInitThread);
-};
-
-enum ThreadEvent {
- // Thread::Init() was called.
- THREAD_EVENT_INIT = 0,
-
- // The MessageLoop for the thread was deleted.
- THREAD_EVENT_MESSAGE_LOOP_DESTROYED,
-
- // Thread::CleanUp() was called.
- THREAD_EVENT_CLEANUP,
-
- // Keep at end of list.
- THREAD_NUM_EVENTS
-};
-
-typedef std::vector<ThreadEvent> EventList;
-
-class CaptureToEventList : public Thread {
- public:
- // This Thread pushes events into the vector |event_list| to show
- // the order they occured in. |event_list| must remain valid for the
- // lifetime of this thread.
- explicit CaptureToEventList(EventList* event_list)
- : Thread("none"),
- event_list_(event_list) {
- }
-
- ~CaptureToEventList() override { Stop(); }
-
- void Init() override { event_list_->push_back(THREAD_EVENT_INIT); }
-
- void CleanUp() override { event_list_->push_back(THREAD_EVENT_CLEANUP); }
-
- private:
- EventList* event_list_;
-
- DISALLOW_COPY_AND_ASSIGN(CaptureToEventList);
-};
-
-// Observer that writes a value into |event_list| when a message loop has been
-// destroyed.
-class CapturingDestructionObserver
- : public base::MessageLoopCurrent::DestructionObserver {
- public:
- // |event_list| must remain valid throughout the observer's lifetime.
- explicit CapturingDestructionObserver(EventList* event_list)
- : event_list_(event_list) {
- }
-
- // DestructionObserver implementation:
- void WillDestroyCurrentMessageLoop() override {
- event_list_->push_back(THREAD_EVENT_MESSAGE_LOOP_DESTROYED);
- event_list_ = nullptr;
- }
-
- private:
- EventList* event_list_;
-
- DISALLOW_COPY_AND_ASSIGN(CapturingDestructionObserver);
-};
-
-// Task that adds a destruction observer to the current message loop.
-void RegisterDestructionObserver(
- base::MessageLoopCurrent::DestructionObserver* observer) {
- base::MessageLoopCurrent::Get()->AddDestructionObserver(observer);
-}
-
-// Task that calls GetThreadId() of |thread|, stores the result into |id|, then
-// signal |event|.
-void ReturnThreadId(base::Thread* thread,
- base::PlatformThreadId* id,
- base::WaitableEvent* event) {
- *id = thread->GetThreadId();
- event->Signal();
-}
-
-} // namespace
-
-TEST_F(ThreadTest, StartWithOptions_StackSize) {
- Thread a("StartWithStackSize");
- // Ensure that the thread can work with only 12 kb and still process a
- // message. At the same time, we should scale with the bitness of the system
- // where 12 kb is definitely not enough.
- // 12 kb = 3072 Slots on a 32-bit system, so we'll scale based off of that.
- Thread::Options options;
-#if defined(ADDRESS_SANITIZER) || !defined(NDEBUG)
- // ASan bloats the stack variables and overflows the 3072 slot stack. Some
- // debug builds also grow the stack too much.
- options.stack_size = 2 * 3072 * sizeof(uintptr_t);
-#else
- options.stack_size = 3072 * sizeof(uintptr_t);
-#endif
- EXPECT_TRUE(a.StartWithOptions(options));
- EXPECT_TRUE(a.message_loop());
- EXPECT_TRUE(a.IsRunning());
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- a.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
- event.Wait();
-}
-
-// Intentional test-only race for otherwise untestable code, won't fix.
-// https://crbug.com/634383
-#if !defined(THREAD_SANITIZER)
-TEST_F(ThreadTest, StartWithOptions_NonJoinable) {
- Thread* a = new Thread("StartNonJoinable");
- // Non-joinable threads have to be leaked for now (see
- // Thread::Options::joinable for details).
- ANNOTATE_LEAKING_OBJECT_PTR(a);
-
- Thread::Options options;
- options.joinable = false;
- EXPECT_TRUE(a->StartWithOptions(options));
- EXPECT_TRUE(a->message_loop());
- EXPECT_TRUE(a->IsRunning());
-
- // Without this call this test is racy. The above IsRunning() succeeds because
- // of an early-return condition while between Start() and StopSoon(), after
- // invoking StopSoon() below this early-return condition is no longer
- // satisfied and the real |is_running_| bit has to be checked. It could still
- // be false if the message loop hasn't started for real in practice. This is
- // only a requirement for this test because the non-joinable property forces
- // it to use StopSoon() and not wait for a complete Stop().
- EXPECT_TRUE(a->WaitUntilThreadStarted());
-
- // Make the thread block until |block_event| is signaled.
- base::WaitableEvent block_event(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- a->task_runner()->PostTask(FROM_HERE,
- base::BindOnce(&base::WaitableEvent::Wait,
- base::Unretained(&block_event)));
-
- a->StopSoon();
- EXPECT_TRUE(a->IsRunning());
-
- // Unblock the task and give a bit of extra time to unwind QuitWhenIdle().
- block_event.Signal();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
-
- // The thread should now have stopped on its own.
- EXPECT_FALSE(a->IsRunning());
-}
-#endif
-
-TEST_F(ThreadTest, TwoTasksOnJoinableThread) {
- bool was_invoked = false;
- {
- Thread a("TwoTasksOnJoinableThread");
- EXPECT_TRUE(a.Start());
- EXPECT_TRUE(a.message_loop());
-
- // Test that all events are dispatched before the Thread object is
- // destroyed. We do this by dispatching a sleep event before the
- // event that will toggle our sentinel value.
- a.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(static_cast<void (*)(base::TimeDelta)>(
- &base::PlatformThread::Sleep),
- base::TimeDelta::FromMilliseconds(20)));
- a.task_runner()->PostTask(FROM_HERE,
- base::BindOnce(&ToggleValue, &was_invoked));
- }
- EXPECT_TRUE(was_invoked);
-}
-
-TEST_F(ThreadTest, DestroyWhileRunningIsSafe) {
- Thread a("DestroyWhileRunningIsSafe");
- EXPECT_TRUE(a.Start());
- EXPECT_TRUE(a.WaitUntilThreadStarted());
-}
-
-// TODO(gab): Enable this test when destroying a non-joinable Thread instance
-// is supported (proposal @ https://crbug.com/629139#c14).
-TEST_F(ThreadTest, DISABLED_DestroyWhileRunningNonJoinableIsSafe) {
- {
- Thread a("DestroyWhileRunningNonJoinableIsSafe");
- Thread::Options options;
- options.joinable = false;
- EXPECT_TRUE(a.StartWithOptions(options));
- EXPECT_TRUE(a.WaitUntilThreadStarted());
- }
-
- // Attempt to catch use-after-frees from the non-joinable thread in the
- // scope of this test if any.
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
-}
-
-TEST_F(ThreadTest, StopSoon) {
- Thread a("StopSoon");
- EXPECT_TRUE(a.Start());
- EXPECT_TRUE(a.message_loop());
- EXPECT_TRUE(a.IsRunning());
- a.StopSoon();
- a.Stop();
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
-}
-
-TEST_F(ThreadTest, StopTwiceNop) {
- Thread a("StopTwiceNop");
- EXPECT_TRUE(a.Start());
- EXPECT_TRUE(a.message_loop());
- EXPECT_TRUE(a.IsRunning());
- a.StopSoon();
- // Calling StopSoon() a second time should be a nop.
- a.StopSoon();
- a.Stop();
- // Same with Stop().
- a.Stop();
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
- // Calling them when not running should also nop.
- a.StopSoon();
- a.Stop();
-}
-
-// TODO(gab): Enable this test in conjunction with re-enabling the sequence
-// check in Thread::Stop() as part of http://crbug.com/629139.
-TEST_F(ThreadTest, DISABLED_StopOnNonOwningThreadIsDeath) {
- Thread a("StopOnNonOwningThreadDeath");
- EXPECT_TRUE(a.StartAndWaitForTesting());
-
- Thread b("NonOwningThread");
- b.Start();
- EXPECT_DCHECK_DEATH({
- // Stopping |a| on |b| isn't allowed.
- b.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&Thread::Stop, base::Unretained(&a)));
- // Block here so the DCHECK on |b| always happens in this scope.
- base::PlatformThread::Sleep(base::TimeDelta::Max());
- });
-}
-
-TEST_F(ThreadTest, TransferOwnershipAndStop) {
- std::unique_ptr<Thread> a =
- std::make_unique<Thread>("TransferOwnershipAndStop");
- EXPECT_TRUE(a->StartAndWaitForTesting());
- EXPECT_TRUE(a->IsRunning());
-
- Thread b("TakingOwnershipThread");
- b.Start();
-
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::MANUAL,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
-
- // a->DetachFromSequence() should allow |b| to use |a|'s Thread API.
- a->DetachFromSequence();
- b.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(
- [](std::unique_ptr<Thread> thread_to_stop,
- base::WaitableEvent* event_to_signal) -> void {
- thread_to_stop->Stop();
- event_to_signal->Signal();
- },
- std::move(a), base::Unretained(&event)));
-
- event.Wait();
-}
-
-TEST_F(ThreadTest, StartTwice) {
- Thread a("StartTwice");
-
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
-
- EXPECT_TRUE(a.Start());
- EXPECT_TRUE(a.message_loop());
- EXPECT_TRUE(a.IsRunning());
-
- a.Stop();
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
-
- EXPECT_TRUE(a.Start());
- EXPECT_TRUE(a.message_loop());
- EXPECT_TRUE(a.IsRunning());
-
- a.Stop();
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
-}
-
-// Intentional test-only race for otherwise untestable code, won't fix.
-// https://crbug.com/634383
-#if !defined(THREAD_SANITIZER)
-TEST_F(ThreadTest, StartTwiceNonJoinableNotAllowed) {
- LOG(ERROR) << __FUNCTION__;
- Thread* a = new Thread("StartTwiceNonJoinable");
- // Non-joinable threads have to be leaked for now (see
- // Thread::Options::joinable for details).
- ANNOTATE_LEAKING_OBJECT_PTR(a);
-
- Thread::Options options;
- options.joinable = false;
- EXPECT_TRUE(a->StartWithOptions(options));
- EXPECT_TRUE(a->message_loop());
- EXPECT_TRUE(a->IsRunning());
-
- // Signaled when last task on |a| is processed.
- base::WaitableEvent last_task_event(
- base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- a->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&base::WaitableEvent::Signal,
- base::Unretained(&last_task_event)));
-
- // StopSoon() is non-blocking, Yield() to |a|, wait for last task to be
- // processed and a little more for QuitWhenIdle() to unwind before considering
- // the thread "stopped".
- a->StopSoon();
- base::PlatformThread::YieldCurrentThread();
- last_task_event.Wait();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(20));
-
- // This test assumes that the above was sufficient to let the thread fully
- // stop.
- ASSERT_FALSE(a->IsRunning());
-
- // Restarting it should not be allowed.
- EXPECT_DCHECK_DEATH(a->Start());
-}
-#endif
-
-TEST_F(ThreadTest, ThreadName) {
- Thread a("ThreadName");
- EXPECT_TRUE(a.Start());
- EXPECT_EQ("ThreadName", a.thread_name());
-}
-
-TEST_F(ThreadTest, ThreadId) {
- Thread a("ThreadId0");
- Thread b("ThreadId1");
- a.Start();
- b.Start();
-
- // Post a task that calls GetThreadId() on the created thread.
- base::WaitableEvent event(base::WaitableEvent::ResetPolicy::AUTOMATIC,
- base::WaitableEvent::InitialState::NOT_SIGNALED);
- base::PlatformThreadId id_from_new_thread;
- a.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(ReturnThreadId, &a, &id_from_new_thread, &event));
-
- // Call GetThreadId() on the current thread before calling event.Wait() so
- // that this test can find a race issue with TSAN.
- base::PlatformThreadId id_from_current_thread = a.GetThreadId();
-
- // Check if GetThreadId() returns consistent value in both threads.
- event.Wait();
- EXPECT_EQ(id_from_current_thread, id_from_new_thread);
-
- // A started thread should have a valid ID.
- EXPECT_NE(base::kInvalidThreadId, a.GetThreadId());
- EXPECT_NE(base::kInvalidThreadId, b.GetThreadId());
-
- // Each thread should have a different thread ID.
- EXPECT_NE(a.GetThreadId(), b.GetThreadId());
-}
-
-TEST_F(ThreadTest, ThreadIdWithRestart) {
- Thread a("ThreadIdWithRestart");
- base::PlatformThreadId previous_id = base::kInvalidThreadId;
-
- for (size_t i = 0; i < 16; ++i) {
- EXPECT_TRUE(a.Start());
- base::PlatformThreadId current_id = a.GetThreadId();
- EXPECT_NE(previous_id, current_id);
- previous_id = current_id;
- a.Stop();
- }
-}
-
-// Make sure Init() is called after Start() and before
-// WaitUntilThreadInitialized() returns.
-TEST_F(ThreadTest, SleepInsideInit) {
- SleepInsideInitThread t;
- EXPECT_FALSE(t.InitCalled());
- t.StartAndWaitForTesting();
- EXPECT_TRUE(t.InitCalled());
-}
-
-// Make sure that the destruction sequence is:
-//
-// (1) Thread::CleanUp()
-// (2) MessageLoop::~MessageLoop()
-// MessageLoopCurrent::DestructionObservers called.
-TEST_F(ThreadTest, CleanUp) {
- EventList captured_events;
- CapturingDestructionObserver loop_destruction_observer(&captured_events);
-
- {
- // Start a thread which writes its event into |captured_events|.
- CaptureToEventList t(&captured_events);
- EXPECT_TRUE(t.Start());
- EXPECT_TRUE(t.message_loop());
- EXPECT_TRUE(t.IsRunning());
-
- // Register an observer that writes into |captured_events| once the
- // thread's message loop is destroyed.
- t.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&RegisterDestructionObserver,
- base::Unretained(&loop_destruction_observer)));
-
- // Upon leaving this scope, the thread is deleted.
- }
-
- // Check the order of events during shutdown.
- ASSERT_EQ(static_cast<size_t>(THREAD_NUM_EVENTS), captured_events.size());
- EXPECT_EQ(THREAD_EVENT_INIT, captured_events[0]);
- EXPECT_EQ(THREAD_EVENT_CLEANUP, captured_events[1]);
- EXPECT_EQ(THREAD_EVENT_MESSAGE_LOOP_DESTROYED, captured_events[2]);
-}
-
-TEST_F(ThreadTest, ThreadNotStarted) {
- Thread a("Inert");
- EXPECT_FALSE(a.task_runner());
-}
-
-TEST_F(ThreadTest, MultipleWaitUntilThreadStarted) {
- Thread a("MultipleWaitUntilThreadStarted");
- EXPECT_TRUE(a.Start());
- // It's OK to call WaitUntilThreadStarted() multiple times.
- EXPECT_TRUE(a.WaitUntilThreadStarted());
- EXPECT_TRUE(a.WaitUntilThreadStarted());
-}
-
-TEST_F(ThreadTest, FlushForTesting) {
- Thread a("FlushForTesting");
-
- // Flushing a non-running thread should be a no-op.
- a.FlushForTesting();
-
- ASSERT_TRUE(a.Start());
-
- // Flushing a thread with no tasks shouldn't block.
- a.FlushForTesting();
-
- constexpr base::TimeDelta kSleepPerTestTask =
- base::TimeDelta::FromMilliseconds(50);
- constexpr size_t kNumSleepTasks = 5;
-
- const base::TimeTicks ticks_before_post = base::TimeTicks::Now();
-
- for (size_t i = 0; i < kNumSleepTasks; ++i) {
- a.task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&base::PlatformThread::Sleep, kSleepPerTestTask));
- }
-
- // All tasks should have executed, as reflected by the elapsed time.
- a.FlushForTesting();
- EXPECT_GE(base::TimeTicks::Now() - ticks_before_post,
- kNumSleepTasks * kSleepPerTestTask);
-
- a.Stop();
-
- // Flushing a stopped thread should be a no-op.
- a.FlushForTesting();
-}
-
-namespace {
-
-// A Thread which uses a MessageLoop on the stack. It won't start a real
-// underlying thread (instead its messages can be processed by a RunLoop on the
-// stack).
-class ExternalMessageLoopThread : public Thread {
- public:
- ExternalMessageLoopThread() : Thread("ExternalMessageLoopThread") {}
-
- ~ExternalMessageLoopThread() override { Stop(); }
-
- void InstallMessageLoop() { SetMessageLoop(&external_message_loop_); }
-
- void VerifyUsingExternalMessageLoop(
- bool expected_using_external_message_loop) {
- EXPECT_EQ(expected_using_external_message_loop,
- using_external_message_loop());
- }
-
- private:
- base::MessageLoop external_message_loop_;
-
- DISALLOW_COPY_AND_ASSIGN(ExternalMessageLoopThread);
-};
-
-} // namespace
-
-TEST_F(ThreadTest, ExternalMessageLoop) {
- ExternalMessageLoopThread a;
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
- a.VerifyUsingExternalMessageLoop(false);
-
- a.InstallMessageLoop();
- EXPECT_TRUE(a.message_loop());
- EXPECT_TRUE(a.IsRunning());
- a.VerifyUsingExternalMessageLoop(true);
-
- bool ran = false;
- a.task_runner()->PostTask(
- FROM_HERE, base::BindOnce([](bool* toggled) { *toggled = true; }, &ran));
- base::RunLoop().RunUntilIdle();
- EXPECT_TRUE(ran);
-
- a.Stop();
- EXPECT_FALSE(a.message_loop());
- EXPECT_FALSE(a.IsRunning());
- a.VerifyUsingExternalMessageLoop(true);
-
- // Confirm that running any remaining tasks posted from Stop() goes smoothly
- // (e.g. https://codereview.chromium.org/2135413003/#ps300001 crashed if
- // StopSoon() posted Thread::ThreadQuitHelper() while |run_loop_| was null).
- base::RunLoop().RunUntilIdle();
-}
diff --git a/base/threading/watchdog_unittest.cc b/base/threading/watchdog_unittest.cc
deleted file mode 100644
index f534a86..0000000
--- 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/pr_time_unittest.cc b/base/time/pr_time_unittest.cc
deleted file mode 100644
index 341d778..0000000
--- a/base/time/pr_time_unittest.cc
+++ /dev/null
@@ -1,289 +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 <stdint.h>
-#include <time.h>
-
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/third_party/nspr/prtime.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using base::Time;
-
-namespace {
-
-// time_t representation of 15th Oct 2007 12:45:00 PDT
-PRTime comparison_time_pdt = 1192477500 * Time::kMicrosecondsPerSecond;
-
-// Time with positive tz offset and fractional seconds:
-// 2013-07-08T11:28:12.441381+02:00
-PRTime comparison_time_2 = INT64_C(1373275692441381); // represented as GMT
-
-// Specialized test fixture allowing time strings without timezones to be
-// tested by comparing them to a known time in the local zone.
-class PRTimeTest : public testing::Test {
- protected:
- void SetUp() override {
- // Use mktime to get a time_t, and turn it into a PRTime by converting
- // seconds to microseconds. Use 15th Oct 2007 12:45:00 local. This
- // must be a time guaranteed to be outside of a DST fallback hour in
- // any timezone.
- struct tm local_comparison_tm = {
- 0, // second
- 45, // minute
- 12, // hour
- 15, // day of month
- 10 - 1, // month
- 2007 - 1900, // year
- 0, // day of week (ignored, output only)
- 0, // day of year (ignored, output only)
- -1 // DST in effect, -1 tells mktime to figure it out
- };
- comparison_time_local_ =
- mktime(&local_comparison_tm) * Time::kMicrosecondsPerSecond;
- ASSERT_GT(comparison_time_local_, 0);
-
- const int microseconds = 441381;
- struct tm local_comparison_tm_2 = {
- 12, // second
- 28, // minute
- 11, // hour
- 8, // day of month
- 7 - 1, // month
- 2013 - 1900, // year
- 0, // day of week (ignored, output only)
- 0, // day of year (ignored, output only)
- -1 // DST in effect, -1 tells mktime to figure it out
- };
- comparison_time_local_2_ =
- mktime(&local_comparison_tm_2) * Time::kMicrosecondsPerSecond;
- ASSERT_GT(comparison_time_local_2_, 0);
- comparison_time_local_2_ += microseconds;
- }
-
- PRTime comparison_time_local_;
- PRTime comparison_time_local_2_;
-};
-
-// Tests the PR_ParseTimeString nspr helper function for
-// a variety of time strings.
-TEST_F(PRTimeTest, ParseTimeTest1) {
- time_t current_time = 0;
- time(¤t_time);
-
- struct tm local_time = {};
- char time_buf[64] = {};
-#if defined(OS_WIN)
- localtime_s(&local_time, ¤t_time);
- asctime_s(time_buf, arraysize(time_buf), &local_time);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- localtime_r(¤t_time, &local_time);
- asctime_r(&local_time, time_buf);
-#endif
-
- PRTime current_time64 = static_cast<PRTime>(current_time) * PR_USEC_PER_SEC;
-
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString(time_buf, PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(current_time64, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest2) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("Mon, 15 Oct 2007 19:45:00 GMT",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_pdt, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest3) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("15 Oct 07 12:45:00", PR_FALSE,
- &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest4) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("15 Oct 07 19:45 GMT", PR_FALSE,
- &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_pdt, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest5) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("Mon Oct 15 12:45 PDT 2007",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_pdt, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest6) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("Monday, Oct 15, 2007 12:45 PM",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest7) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("10/15/07 12:45:00 PM", PR_FALSE,
- &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest8) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("10/15/07 12:45:00. PM", PR_FALSE,
- &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest9) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("10/15/07 12:45:00.0 PM", PR_FALSE,
- &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest10) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("15-OCT-2007 12:45pm", PR_FALSE,
- &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTest11) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("16 Oct 2007 4:45-JST (Tuesday)",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_pdt, parsed_time);
-}
-
-// hh:mm timezone offset.
-TEST_F(PRTimeTest, ParseTimeTest12) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381+02:00",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_2, parsed_time);
-}
-
-// hhmm timezone offset.
-TEST_F(PRTimeTest, ParseTimeTest13) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381+0200",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_2, parsed_time);
-}
-
-// hh timezone offset.
-TEST_F(PRTimeTest, ParseTimeTest14) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.4413819+02",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_2, parsed_time);
-}
-
-// 5 digits fractional second.
-TEST_F(PRTimeTest, ParseTimeTest15) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08T09:28:12.44138Z",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_2-1, parsed_time);
-}
-
-// Fractional seconds, local timezone.
-TEST_F(PRTimeTest, ParseTimeTest16) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08T11:28:12.441381",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_local_2_, parsed_time);
-}
-
-// "Z" (=GMT) timezone.
-TEST_F(PRTimeTest, ParseTimeTest17) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08T09:28:12.441381Z",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_2, parsed_time);
-}
-
-// "T" delimiter replaced by space.
-TEST_F(PRTimeTest, ParseTimeTest18) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-08 09:28:12.441381Z",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_2, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTestInvalid1) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("201-07-08T09:28:12.441381Z",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_FAILURE, result);
-}
-
-TEST_F(PRTimeTest, ParseTimeTestInvalid2) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-007-08T09:28:12.441381Z",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_FAILURE, result);
-}
-
-TEST_F(PRTimeTest, ParseTimeTestInvalid3) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("2013-07-008T09:28:12.441381Z",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_FAILURE, result);
-}
-
-// This test should not crash when compiled with Visual C++ 2005 (see
-// http://crbug.com/4387).
-TEST_F(PRTimeTest, ParseTimeTestOutOfRange) {
- PRTime parsed_time = 0;
- // Note the lack of timezone in the time string. The year has to be 3001.
- // The date has to be after 23:59:59, December 31, 3000, US Pacific Time, so
- // we use January 2, 3001 to make sure it's after the magic maximum in any
- // timezone.
- PRStatus result = PR_ParseTimeString("Sun Jan 2 00:00:00 3001",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
-}
-
-TEST_F(PRTimeTest, ParseTimeTestNotNormalized1) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("Mon Oct 15 12:44:60 PDT 2007",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_pdt, parsed_time);
-}
-
-TEST_F(PRTimeTest, ParseTimeTestNotNormalized2) {
- PRTime parsed_time = 0;
- PRStatus result = PR_ParseTimeString("Sun Oct 14 36:45 PDT 2007",
- PR_FALSE, &parsed_time);
- EXPECT_EQ(PR_SUCCESS, result);
- EXPECT_EQ(comparison_time_pdt, parsed_time);
-}
-
-} // namespace
diff --git a/base/time/time_unittest.cc b/base/time/time_unittest.cc
deleted file mode 100644
index 0471dd4..0000000
--- a/base/time/time_unittest.cc
+++ /dev/null
@@ -1,1588 +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/time/time.h"
-
-#include <stdint.h>
-#include <time.h>
-#include <limits>
-#include <string>
-
-#include "base/build_time.h"
-#include "base/compiler_specific.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/threading/platform_thread.h"
-#include "base/time/time_override.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#if defined(OS_ANDROID)
-#include "base/android/jni_android.h"
-#elif defined(OS_IOS)
-#include "base/ios/ios_util.h"
-#elif defined(OS_WIN)
-#include <windows.h>
-#endif
-
-namespace base {
-
-namespace {
-
-TEST(TimeTestOutOfBounds, FromExplodedOutOfBoundsTime) {
- // FromUTCExploded must set time to Time(0) and failure, if the day is set to
- // 31 on a 28-30 day month. Test |exploded| returns Time(0) on 31st of
- // February and 31st of April. New implementation handles this.
-
- const struct DateTestData {
- Time::Exploded explode;
- bool is_valid;
- } kDateTestData[] = {
- // 31st of February
- {{2016, 2, 0, 31, 12, 30, 0, 0}, true},
- // 31st of April
- {{2016, 4, 0, 31, 8, 43, 0, 0}, true},
- // Negative month
- {{2016, -5, 0, 2, 4, 10, 0, 0}, false},
- // Negative date of month
- {{2016, 6, 0, -15, 2, 50, 0, 0}, false},
- // Negative hours
- {{2016, 7, 0, 10, -11, 29, 0, 0}, false},
- // Negative minutes
- {{2016, 3, 0, 14, 10, -29, 0, 0}, false},
- // Negative seconds
- {{2016, 10, 0, 25, 7, 47, -30, 0}, false},
- // Negative milliseconds
- {{2016, 10, 0, 25, 7, 47, 20, -500}, false},
- // Hours are too large
- {{2016, 7, 0, 10, 26, 29, 0, 0}, false},
- // Minutes are too large
- {{2016, 3, 0, 14, 10, 78, 0, 0}, false},
- // Seconds are too large
- {{2016, 10, 0, 25, 7, 47, 234, 0}, false},
- // Milliseconds are too large
- {{2016, 10, 0, 25, 6, 31, 23, 1643}, false},
- // Test overflow. Time is valid, but overflow case
- // results in Time(0).
- {{9840633, 1, 0, 1, 1, 1, 0, 0}, true},
- // Underflow will fail as well.
- {{-9840633, 1, 0, 1, 1, 1, 0, 0}, true},
- // Test integer overflow and underflow cases for the values themselves.
- {{std::numeric_limits<int>::min(), 1, 0, 1, 1, 1, 0, 0}, true},
- {{std::numeric_limits<int>::max(), 1, 0, 1, 1, 1, 0, 0}, true},
- {{2016, std::numeric_limits<int>::min(), 0, 1, 1, 1, 0, 0}, false},
- {{2016, std::numeric_limits<int>::max(), 0, 1, 1, 1, 0, 0}, false},
- };
-
- for (const auto& test : kDateTestData) {
- EXPECT_EQ(test.explode.HasValidValues(), test.is_valid);
-
- base::Time result;
- EXPECT_FALSE(base::Time::FromUTCExploded(test.explode, &result));
- EXPECT_TRUE(result.is_null());
- EXPECT_FALSE(base::Time::FromLocalExploded(test.explode, &result));
- EXPECT_TRUE(result.is_null());
- }
-}
-
-// Specialized test fixture allowing time strings without timezones to be
-// tested by comparing them to a known time in the local zone.
-// See also pr_time_unittests.cc
-class TimeTest : public testing::Test {
- protected:
- void SetUp() override {
- // Use mktime to get a time_t, and turn it into a PRTime by converting
- // seconds to microseconds. Use 15th Oct 2007 12:45:00 local. This
- // must be a time guaranteed to be outside of a DST fallback hour in
- // any timezone.
- struct tm local_comparison_tm = {
- 0, // second
- 45, // minute
- 12, // hour
- 15, // day of month
- 10 - 1, // month
- 2007 - 1900, // year
- 0, // day of week (ignored, output only)
- 0, // day of year (ignored, output only)
- -1 // DST in effect, -1 tells mktime to figure it out
- };
-
- time_t converted_time = mktime(&local_comparison_tm);
- ASSERT_GT(converted_time, 0);
- comparison_time_local_ = Time::FromTimeT(converted_time);
-
- // time_t representation of 15th Oct 2007 12:45:00 PDT
- comparison_time_pdt_ = Time::FromTimeT(1192477500);
- }
-
- Time comparison_time_local_;
- Time comparison_time_pdt_;
-};
-
-// Test conversion to/from TimeDeltas elapsed since the Windows epoch.
-// Conversions should be idempotent and non-lossy.
-TEST_F(TimeTest, DeltaSinceWindowsEpoch) {
- const TimeDelta delta = TimeDelta::FromMicroseconds(123);
- EXPECT_EQ(delta,
- Time::FromDeltaSinceWindowsEpoch(delta).ToDeltaSinceWindowsEpoch());
-
- const Time now = Time::Now();
- const Time actual =
- Time::FromDeltaSinceWindowsEpoch(now.ToDeltaSinceWindowsEpoch());
- EXPECT_EQ(now, actual);
-
- // Null times should remain null after a round-trip conversion. This is an
- // important invariant for the common use case of serialization +
- // deserialization.
- const Time should_be_null =
- Time::FromDeltaSinceWindowsEpoch(Time().ToDeltaSinceWindowsEpoch());
- EXPECT_TRUE(should_be_null.is_null());
-}
-
-// Test conversion to/from time_t.
-TEST_F(TimeTest, TimeT) {
- EXPECT_EQ(10, Time().FromTimeT(10).ToTimeT());
- EXPECT_EQ(10.0, Time().FromTimeT(10).ToDoubleT());
-
- // Conversions of 0 should stay 0.
- EXPECT_EQ(0, Time().ToTimeT());
- EXPECT_EQ(0, Time::FromTimeT(0).ToInternalValue());
-}
-
-// Test conversions to/from time_t and exploding/unexploding (utc time).
-TEST_F(TimeTest, UTCTimeT) {
- // C library time and exploded time.
- time_t now_t_1 = time(nullptr);
- struct tm tms;
-#if defined(OS_WIN)
- gmtime_s(&tms, &now_t_1);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- gmtime_r(&now_t_1, &tms);
-#endif
-
- // Convert to ours.
- Time our_time_1 = Time::FromTimeT(now_t_1);
- Time::Exploded exploded;
- our_time_1.UTCExplode(&exploded);
-
- // This will test both our exploding and our time_t -> Time conversion.
- EXPECT_EQ(tms.tm_year + 1900, exploded.year);
- EXPECT_EQ(tms.tm_mon + 1, exploded.month);
- EXPECT_EQ(tms.tm_mday, exploded.day_of_month);
- EXPECT_EQ(tms.tm_hour, exploded.hour);
- EXPECT_EQ(tms.tm_min, exploded.minute);
- EXPECT_EQ(tms.tm_sec, exploded.second);
-
- // Convert exploded back to the time struct.
- Time our_time_2;
- EXPECT_TRUE(Time::FromUTCExploded(exploded, &our_time_2));
- EXPECT_TRUE(our_time_1 == our_time_2);
-
- time_t now_t_2 = our_time_2.ToTimeT();
- EXPECT_EQ(now_t_1, now_t_2);
-}
-
-// Test conversions to/from time_t and exploding/unexploding (local time).
-TEST_F(TimeTest, LocalTimeT) {
-#if defined(OS_IOS) && TARGET_OS_SIMULATOR
- // The function CFTimeZoneCopySystem() fails to determine the system timezone
- // when running iOS 11.0 simulator on an host running High Sierra and return
- // the "GMT" timezone. This causes Time::LocalExplode and localtime_r values
- // to differ by the local timezone offset. Disable the test if simulating
- // iOS 10.0 as it is not possible to check the version of the host mac.
- // TODO(crbug.com/782033): remove this once support for iOS pre-11.0 is
- // dropped or when the bug in CFTimeZoneCopySystem() is fixed.
- if (ios::IsRunningOnIOS10OrLater() && !ios::IsRunningOnIOS11OrLater()) {
- return;
- }
-#endif
-
- // C library time and exploded time.
- time_t now_t_1 = time(nullptr);
- struct tm tms;
-#if defined(OS_WIN)
- localtime_s(&tms, &now_t_1);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- localtime_r(&now_t_1, &tms);
-#endif
-
- // Convert to ours.
- Time our_time_1 = Time::FromTimeT(now_t_1);
- Time::Exploded exploded;
- our_time_1.LocalExplode(&exploded);
-
- // This will test both our exploding and our time_t -> Time conversion.
- EXPECT_EQ(tms.tm_year + 1900, exploded.year);
- EXPECT_EQ(tms.tm_mon + 1, exploded.month);
- EXPECT_EQ(tms.tm_mday, exploded.day_of_month);
- EXPECT_EQ(tms.tm_hour, exploded.hour);
- EXPECT_EQ(tms.tm_min, exploded.minute);
- EXPECT_EQ(tms.tm_sec, exploded.second);
-
- // Convert exploded back to the time struct.
- Time our_time_2;
- EXPECT_TRUE(Time::FromLocalExploded(exploded, &our_time_2));
- EXPECT_TRUE(our_time_1 == our_time_2);
-
- time_t now_t_2 = our_time_2.ToTimeT();
- EXPECT_EQ(now_t_1, now_t_2);
-}
-
-// Test conversions to/from javascript time.
-TEST_F(TimeTest, JsTime) {
- Time epoch = Time::FromJsTime(0.0);
- EXPECT_EQ(epoch, Time::UnixEpoch());
- Time t = Time::FromJsTime(700000.3);
- EXPECT_EQ(700.0003, t.ToDoubleT());
- t = Time::FromDoubleT(800.73);
- EXPECT_EQ(800730.0, t.ToJsTime());
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-TEST_F(TimeTest, FromTimeVal) {
- Time now = Time::Now();
- Time also_now = Time::FromTimeVal(now.ToTimeVal());
- EXPECT_EQ(now, also_now);
-}
-#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-TEST_F(TimeTest, FromExplodedWithMilliseconds) {
- // Some platform implementations of FromExploded are liable to drop
- // milliseconds if we aren't careful.
- Time now = Time::NowFromSystemTime();
- Time::Exploded exploded1 = {0};
- now.UTCExplode(&exploded1);
- exploded1.millisecond = 500;
- Time time;
- EXPECT_TRUE(Time::FromUTCExploded(exploded1, &time));
- Time::Exploded exploded2 = {0};
- time.UTCExplode(&exploded2);
- EXPECT_EQ(exploded1.millisecond, exploded2.millisecond);
-}
-
-TEST_F(TimeTest, ZeroIsSymmetric) {
- Time zero_time(Time::FromTimeT(0));
- EXPECT_EQ(0, zero_time.ToTimeT());
-
- EXPECT_EQ(0.0, zero_time.ToDoubleT());
-}
-
-TEST_F(TimeTest, LocalExplode) {
- Time a = Time::Now();
- Time::Exploded exploded;
- a.LocalExplode(&exploded);
-
- Time b;
- EXPECT_TRUE(Time::FromLocalExploded(exploded, &b));
-
- // The exploded structure doesn't have microseconds, and on Mac & Linux, the
- // internal OS conversion uses seconds, which will cause truncation. So we
- // can only make sure that the delta is within one second.
- EXPECT_TRUE((a - b) < TimeDelta::FromSeconds(1));
-}
-
-TEST_F(TimeTest, UTCExplode) {
- Time a = Time::Now();
- Time::Exploded exploded;
- a.UTCExplode(&exploded);
-
- Time b;
- EXPECT_TRUE(Time::FromUTCExploded(exploded, &b));
- EXPECT_TRUE((a - b) < TimeDelta::FromSeconds(1));
-}
-
-TEST_F(TimeTest, LocalMidnight) {
- Time::Exploded exploded;
- Time::Now().LocalMidnight().LocalExplode(&exploded);
- EXPECT_EQ(0, exploded.hour);
- EXPECT_EQ(0, exploded.minute);
- EXPECT_EQ(0, exploded.second);
- EXPECT_EQ(0, exploded.millisecond);
-}
-
-TEST_F(TimeTest, ParseTimeTest1) {
- time_t current_time = 0;
- time(¤t_time);
-
- struct tm local_time = {};
- char time_buf[64] = {};
-#if defined(OS_WIN)
- localtime_s(&local_time, ¤t_time);
- asctime_s(time_buf, arraysize(time_buf), &local_time);
-#elif defined(OS_POSIX) || defined(OS_FUCHSIA)
- localtime_r(¤t_time, &local_time);
- asctime_r(&local_time, time_buf);
-#endif
-
- Time parsed_time;
- EXPECT_TRUE(Time::FromString(time_buf, &parsed_time));
- EXPECT_EQ(current_time, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, DayOfWeekSunday) {
- Time time;
- EXPECT_TRUE(Time::FromString("Sun, 06 May 2012 12:00:00 GMT", &time));
- Time::Exploded exploded;
- time.UTCExplode(&exploded);
- EXPECT_EQ(0, exploded.day_of_week);
-}
-
-TEST_F(TimeTest, DayOfWeekWednesday) {
- Time time;
- EXPECT_TRUE(Time::FromString("Wed, 09 May 2012 12:00:00 GMT", &time));
- Time::Exploded exploded;
- time.UTCExplode(&exploded);
- EXPECT_EQ(3, exploded.day_of_week);
-}
-
-TEST_F(TimeTest, DayOfWeekSaturday) {
- Time time;
- EXPECT_TRUE(Time::FromString("Sat, 12 May 2012 12:00:00 GMT", &time));
- Time::Exploded exploded;
- time.UTCExplode(&exploded);
- EXPECT_EQ(6, exploded.day_of_week);
-}
-
-TEST_F(TimeTest, ParseTimeTest2) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("Mon, 15 Oct 2007 19:45:00 GMT", &parsed_time));
- EXPECT_EQ(comparison_time_pdt_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest3) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("15 Oct 07 12:45:00", &parsed_time));
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest4) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("15 Oct 07 19:45 GMT", &parsed_time));
- EXPECT_EQ(comparison_time_pdt_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest5) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("Mon Oct 15 12:45 PDT 2007", &parsed_time));
- EXPECT_EQ(comparison_time_pdt_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest6) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("Monday, Oct 15, 2007 12:45 PM", &parsed_time));
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest7) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("10/15/07 12:45:00 PM", &parsed_time));
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest8) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("15-OCT-2007 12:45pm", &parsed_time));
- EXPECT_EQ(comparison_time_local_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest9) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("16 Oct 2007 4:45-JST (Tuesday)", &parsed_time));
- EXPECT_EQ(comparison_time_pdt_, parsed_time);
-}
-
-TEST_F(TimeTest, ParseTimeTest10) {
- Time parsed_time;
- EXPECT_TRUE(Time::FromString("15/10/07 12:45", &parsed_time));
- EXPECT_EQ(parsed_time, comparison_time_local_);
-}
-
-// Test some of edge cases around epoch, etc.
-TEST_F(TimeTest, ParseTimeTestEpoch0) {
- Time parsed_time;
-
- // time_t == epoch == 0
- EXPECT_TRUE(Time::FromString("Thu Jan 01 01:00:00 +0100 1970",
- &parsed_time));
- EXPECT_EQ(0, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Thu Jan 01 00:00:00 GMT 1970",
- &parsed_time));
- EXPECT_EQ(0, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, ParseTimeTestEpoch1) {
- Time parsed_time;
-
- // time_t == 1 second after epoch == 1
- EXPECT_TRUE(Time::FromString("Thu Jan 01 01:00:01 +0100 1970",
- &parsed_time));
- EXPECT_EQ(1, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Thu Jan 01 00:00:01 GMT 1970",
- &parsed_time));
- EXPECT_EQ(1, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, ParseTimeTestEpoch2) {
- Time parsed_time;
-
- // time_t == 2 seconds after epoch == 2
- EXPECT_TRUE(Time::FromString("Thu Jan 01 01:00:02 +0100 1970",
- &parsed_time));
- EXPECT_EQ(2, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Thu Jan 01 00:00:02 GMT 1970",
- &parsed_time));
- EXPECT_EQ(2, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, ParseTimeTestEpochNeg1) {
- Time parsed_time;
-
- // time_t == 1 second before epoch == -1
- EXPECT_TRUE(Time::FromString("Thu Jan 01 00:59:59 +0100 1970",
- &parsed_time));
- EXPECT_EQ(-1, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Wed Dec 31 23:59:59 GMT 1969",
- &parsed_time));
- EXPECT_EQ(-1, parsed_time.ToTimeT());
-}
-
-// If time_t is 32 bits, a date after year 2038 will overflow time_t and
-// cause timegm() to return -1. The parsed time should not be 1 second
-// before epoch.
-TEST_F(TimeTest, ParseTimeTestEpochNotNeg1) {
- Time parsed_time;
-
- EXPECT_TRUE(Time::FromString("Wed Dec 31 23:59:59 GMT 2100",
- &parsed_time));
- EXPECT_NE(-1, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, ParseTimeTestEpochNeg2) {
- Time parsed_time;
-
- // time_t == 2 seconds before epoch == -2
- EXPECT_TRUE(Time::FromString("Thu Jan 01 00:59:58 +0100 1970",
- &parsed_time));
- EXPECT_EQ(-2, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Wed Dec 31 23:59:58 GMT 1969",
- &parsed_time));
- EXPECT_EQ(-2, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, ParseTimeTestEpoch1960) {
- Time parsed_time;
-
- // time_t before Epoch, in 1960
- EXPECT_TRUE(Time::FromString("Wed Jun 29 19:40:01 +0100 1960",
- &parsed_time));
- EXPECT_EQ(-299999999, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Wed Jun 29 18:40:01 GMT 1960",
- &parsed_time));
- EXPECT_EQ(-299999999, parsed_time.ToTimeT());
- EXPECT_TRUE(Time::FromString("Wed Jun 29 17:40:01 GMT 1960",
- &parsed_time));
- EXPECT_EQ(-300003599, parsed_time.ToTimeT());
-}
-
-TEST_F(TimeTest, ParseTimeTestEmpty) {
- Time parsed_time;
- EXPECT_FALSE(Time::FromString("", &parsed_time));
-}
-
-TEST_F(TimeTest, ParseTimeTestInvalidString) {
- Time parsed_time;
- EXPECT_FALSE(Time::FromString("Monday morning 2000", &parsed_time));
-}
-
-TEST_F(TimeTest, ExplodeBeforeUnixEpoch) {
- static const int kUnixEpochYear = 1970; // In case this changes (ha!).
- Time t;
- Time::Exploded exploded;
-
- t = Time::UnixEpoch() - TimeDelta::FromMicroseconds(1);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1969-12-31 23:59:59 999 milliseconds (and 999 microseconds).
- EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
- EXPECT_EQ(12, exploded.month);
- EXPECT_EQ(31, exploded.day_of_month);
- EXPECT_EQ(23, exploded.hour);
- EXPECT_EQ(59, exploded.minute);
- EXPECT_EQ(59, exploded.second);
- EXPECT_EQ(999, exploded.millisecond);
-
- t = Time::UnixEpoch() - TimeDelta::FromMicroseconds(1000);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1969-12-31 23:59:59 999 milliseconds.
- EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
- EXPECT_EQ(12, exploded.month);
- EXPECT_EQ(31, exploded.day_of_month);
- EXPECT_EQ(23, exploded.hour);
- EXPECT_EQ(59, exploded.minute);
- EXPECT_EQ(59, exploded.second);
- EXPECT_EQ(999, exploded.millisecond);
-
- t = Time::UnixEpoch() - TimeDelta::FromMicroseconds(1001);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1969-12-31 23:59:59 998 milliseconds (and 999 microseconds).
- EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
- EXPECT_EQ(12, exploded.month);
- EXPECT_EQ(31, exploded.day_of_month);
- EXPECT_EQ(23, exploded.hour);
- EXPECT_EQ(59, exploded.minute);
- EXPECT_EQ(59, exploded.second);
- EXPECT_EQ(998, exploded.millisecond);
-
- t = Time::UnixEpoch() - TimeDelta::FromMilliseconds(1000);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1969-12-31 23:59:59.
- EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
- EXPECT_EQ(12, exploded.month);
- EXPECT_EQ(31, exploded.day_of_month);
- EXPECT_EQ(23, exploded.hour);
- EXPECT_EQ(59, exploded.minute);
- EXPECT_EQ(59, exploded.second);
- EXPECT_EQ(0, exploded.millisecond);
-
- t = Time::UnixEpoch() - TimeDelta::FromMilliseconds(1001);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1969-12-31 23:59:58 999 milliseconds.
- EXPECT_EQ(kUnixEpochYear - 1, exploded.year);
- EXPECT_EQ(12, exploded.month);
- EXPECT_EQ(31, exploded.day_of_month);
- EXPECT_EQ(23, exploded.hour);
- EXPECT_EQ(59, exploded.minute);
- EXPECT_EQ(58, exploded.second);
- EXPECT_EQ(999, exploded.millisecond);
-
- // Make sure we still handle at/after Unix epoch correctly.
- t = Time::UnixEpoch();
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1970-12-31 00:00:00 0 milliseconds.
- EXPECT_EQ(kUnixEpochYear, exploded.year);
- EXPECT_EQ(1, exploded.month);
- EXPECT_EQ(1, exploded.day_of_month);
- EXPECT_EQ(0, exploded.hour);
- EXPECT_EQ(0, exploded.minute);
- EXPECT_EQ(0, exploded.second);
- EXPECT_EQ(0, exploded.millisecond);
-
- t = Time::UnixEpoch() + TimeDelta::FromMicroseconds(1);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1970-01-01 00:00:00 0 milliseconds (and 1 microsecond).
- EXPECT_EQ(kUnixEpochYear, exploded.year);
- EXPECT_EQ(1, exploded.month);
- EXPECT_EQ(1, exploded.day_of_month);
- EXPECT_EQ(0, exploded.hour);
- EXPECT_EQ(0, exploded.minute);
- EXPECT_EQ(0, exploded.second);
- EXPECT_EQ(0, exploded.millisecond);
-
- t = Time::UnixEpoch() + TimeDelta::FromMicroseconds(1000);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1970-01-01 00:00:00 1 millisecond.
- EXPECT_EQ(kUnixEpochYear, exploded.year);
- EXPECT_EQ(1, exploded.month);
- EXPECT_EQ(1, exploded.day_of_month);
- EXPECT_EQ(0, exploded.hour);
- EXPECT_EQ(0, exploded.minute);
- EXPECT_EQ(0, exploded.second);
- EXPECT_EQ(1, exploded.millisecond);
-
- t = Time::UnixEpoch() + TimeDelta::FromMilliseconds(1000);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1970-01-01 00:00:01.
- EXPECT_EQ(kUnixEpochYear, exploded.year);
- EXPECT_EQ(1, exploded.month);
- EXPECT_EQ(1, exploded.day_of_month);
- EXPECT_EQ(0, exploded.hour);
- EXPECT_EQ(0, exploded.minute);
- EXPECT_EQ(1, exploded.second);
- EXPECT_EQ(0, exploded.millisecond);
-
- t = Time::UnixEpoch() + TimeDelta::FromMilliseconds(1001);
- t.UTCExplode(&exploded);
- EXPECT_TRUE(exploded.HasValidValues());
- // Should be 1970-01-01 00:00:01 1 millisecond.
- EXPECT_EQ(kUnixEpochYear, exploded.year);
- EXPECT_EQ(1, exploded.month);
- EXPECT_EQ(1, exploded.day_of_month);
- EXPECT_EQ(0, exploded.hour);
- EXPECT_EQ(0, exploded.minute);
- EXPECT_EQ(1, exploded.second);
- EXPECT_EQ(1, exploded.millisecond);
-}
-
-TEST_F(TimeTest, Max) {
- Time max = Time::Max();
- EXPECT_TRUE(max.is_max());
- EXPECT_EQ(max, Time::Max());
- EXPECT_GT(max, Time::Now());
- EXPECT_GT(max, Time());
-}
-
-TEST_F(TimeTest, MaxConversions) {
- Time t = Time::Max();
- EXPECT_EQ(std::numeric_limits<int64_t>::max(), t.ToInternalValue());
-
- t = Time::FromDoubleT(std::numeric_limits<double>::infinity());
- EXPECT_TRUE(t.is_max());
- EXPECT_EQ(std::numeric_limits<double>::infinity(), t.ToDoubleT());
-
- t = Time::FromJsTime(std::numeric_limits<double>::infinity());
- EXPECT_TRUE(t.is_max());
- EXPECT_EQ(std::numeric_limits<double>::infinity(), t.ToJsTime());
-
- t = Time::FromTimeT(std::numeric_limits<time_t>::max());
- EXPECT_TRUE(t.is_max());
- EXPECT_EQ(std::numeric_limits<time_t>::max(), t.ToTimeT());
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
- struct timeval tval;
- tval.tv_sec = std::numeric_limits<time_t>::max();
- tval.tv_usec = static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1;
- t = Time::FromTimeVal(tval);
- EXPECT_TRUE(t.is_max());
- tval = t.ToTimeVal();
- EXPECT_EQ(std::numeric_limits<time_t>::max(), tval.tv_sec);
- EXPECT_EQ(static_cast<suseconds_t>(Time::kMicrosecondsPerSecond) - 1,
- tval.tv_usec);
-#endif
-
-#if defined(OS_MACOSX)
- t = Time::FromCFAbsoluteTime(std::numeric_limits<CFAbsoluteTime>::infinity());
- EXPECT_TRUE(t.is_max());
- EXPECT_EQ(std::numeric_limits<CFAbsoluteTime>::infinity(),
- t.ToCFAbsoluteTime());
-#endif
-
-#if defined(OS_WIN)
- FILETIME ftime;
- ftime.dwHighDateTime = std::numeric_limits<DWORD>::max();
- ftime.dwLowDateTime = std::numeric_limits<DWORD>::max();
- t = Time::FromFileTime(ftime);
- EXPECT_TRUE(t.is_max());
- ftime = t.ToFileTime();
- EXPECT_EQ(std::numeric_limits<DWORD>::max(), ftime.dwHighDateTime);
- EXPECT_EQ(std::numeric_limits<DWORD>::max(), ftime.dwLowDateTime);
-#endif
-}
-
-#if defined(OS_MACOSX)
-TEST_F(TimeTest, TimeTOverflow) {
- Time t = Time::FromInternalValue(std::numeric_limits<int64_t>::max() - 1);
- EXPECT_FALSE(t.is_max());
- EXPECT_EQ(std::numeric_limits<time_t>::max(), t.ToTimeT());
-}
-#endif
-
-#if defined(OS_ANDROID)
-TEST_F(TimeTest, FromLocalExplodedCrashOnAndroid) {
- // This crashed inside Time:: FromLocalExploded() on Android 4.1.2.
- // See http://crbug.com/287821
- Time::Exploded midnight = {2013, // year
- 10, // month
- 0, // day_of_week
- 13, // day_of_month
- 0, // hour
- 0, // minute
- 0, // second
- };
- // The string passed to putenv() must be a char* and the documentation states
- // that it 'becomes part of the environment', so use a static buffer.
- static char buffer[] = "TZ=America/Santiago";
- putenv(buffer);
- tzset();
- Time t;
- EXPECT_TRUE(Time::FromLocalExploded(midnight, &t));
- EXPECT_EQ(1381633200, t.ToTimeT());
-}
-#endif // OS_ANDROID
-
-TEST_F(TimeTest, FromExploded_MinMax) {
- Time::Exploded exploded = {0};
- exploded.month = 1;
- exploded.day_of_month = 1;
-
- Time parsed_time;
-
- if (Time::kExplodedMinYear != std::numeric_limits<int>::min()) {
- exploded.year = Time::kExplodedMinYear;
- EXPECT_TRUE(Time::FromUTCExploded(exploded, &parsed_time));
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
- // On Windows, January 1, 1601 00:00:00 is actually the null time.
- EXPECT_FALSE(parsed_time.is_null());
-#endif
-
-#if !defined(OS_ANDROID) && !defined(OS_MACOSX)
- // The dates earlier than |kExplodedMinYear| that don't work are OS version
- // dependent on Android and Mac (for example, macOS 10.13 seems to support
- // dates before 1902).
- exploded.year--;
- EXPECT_FALSE(Time::FromUTCExploded(exploded, &parsed_time));
- EXPECT_TRUE(parsed_time.is_null());
-#endif
- }
-
- if (Time::kExplodedMaxYear != std::numeric_limits<int>::max()) {
- exploded.year = Time::kExplodedMaxYear;
- exploded.month = 12;
- exploded.day_of_month = 31;
- exploded.hour = 23;
- exploded.minute = 59;
- exploded.second = 59;
- exploded.millisecond = 999;
- EXPECT_TRUE(Time::FromUTCExploded(exploded, &parsed_time));
- EXPECT_FALSE(parsed_time.is_null());
-
- exploded.year++;
- EXPECT_FALSE(Time::FromUTCExploded(exploded, &parsed_time));
- EXPECT_TRUE(parsed_time.is_null());
- }
-}
-
-class TimeOverride {
- public:
- static Time Now() {
- now_time_ += TimeDelta::FromSeconds(1);
- return now_time_;
- }
-
- static Time now_time_;
-};
-
-// static
-Time TimeOverride::now_time_;
-
-TEST_F(TimeTest, NowOverride) {
- TimeOverride::now_time_ = Time::UnixEpoch();
-
- // Choose a reference time that we know to be in the past but close to now.
- Time build_time = GetBuildTime();
-
- // Override is not active. All Now() methods should return a time greater than
- // the build time.
- EXPECT_LT(build_time, Time::Now());
- EXPECT_GT(Time::Max(), Time::Now());
- EXPECT_LT(build_time, subtle::TimeNowIgnoringOverride());
- EXPECT_GT(Time::Max(), subtle::TimeNowIgnoringOverride());
- EXPECT_LT(build_time, Time::NowFromSystemTime());
- EXPECT_GT(Time::Max(), Time::NowFromSystemTime());
- EXPECT_LT(build_time, subtle::TimeNowFromSystemTimeIgnoringOverride());
- EXPECT_GT(Time::Max(), subtle::TimeNowFromSystemTimeIgnoringOverride());
-
- {
- // Set override.
- subtle::ScopedTimeClockOverrides overrides(&TimeOverride::Now, nullptr,
- nullptr);
-
- // Overridden value is returned and incremented when Now() or
- // NowFromSystemTime() is called.
- EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(1), Time::Now());
- EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(2), Time::Now());
- EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(3),
- Time::NowFromSystemTime());
- EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(4),
- Time::NowFromSystemTime());
-
- // IgnoringOverride methods still return real time.
- EXPECT_LT(build_time, subtle::TimeNowIgnoringOverride());
- EXPECT_GT(Time::Max(), subtle::TimeNowIgnoringOverride());
- EXPECT_LT(build_time, subtle::TimeNowFromSystemTimeIgnoringOverride());
- EXPECT_GT(Time::Max(), subtle::TimeNowFromSystemTimeIgnoringOverride());
-
- // IgnoringOverride methods didn't call NowOverrideClock::Now().
- EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(5), Time::Now());
- EXPECT_EQ(Time::UnixEpoch() + TimeDelta::FromSeconds(6),
- Time::NowFromSystemTime());
- }
-
- // All methods return real time again.
- EXPECT_LT(build_time, Time::Now());
- EXPECT_GT(Time::Max(), Time::Now());
- EXPECT_LT(build_time, subtle::TimeNowIgnoringOverride());
- EXPECT_GT(Time::Max(), subtle::TimeNowIgnoringOverride());
- EXPECT_LT(build_time, Time::NowFromSystemTime());
- EXPECT_GT(Time::Max(), Time::NowFromSystemTime());
- EXPECT_LT(build_time, subtle::TimeNowFromSystemTimeIgnoringOverride());
- EXPECT_GT(Time::Max(), subtle::TimeNowFromSystemTimeIgnoringOverride());
-}
-
-TEST(TimeTicks, Deltas) {
- for (int index = 0; index < 50; index++) {
- TimeTicks ticks_start = TimeTicks::Now();
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
- TimeTicks ticks_stop = TimeTicks::Now();
- TimeDelta delta = ticks_stop - ticks_start;
- // Note: Although we asked for a 10ms sleep, if the
- // time clock has a finer granularity than the Sleep()
- // clock, it is quite possible to wakeup early. Here
- // is how that works:
- // Time(ms timer) Time(us timer)
- // 5 5010
- // 6 6010
- // 7 7010
- // 8 8010
- // 9 9000
- // Elapsed 4ms 3990us
- //
- // Unfortunately, our InMilliseconds() function truncates
- // rather than rounds. We should consider fixing this
- // so that our averages come out better.
- EXPECT_GE(delta.InMilliseconds(), 9);
- EXPECT_GE(delta.InMicroseconds(), 9000);
- EXPECT_EQ(delta.InSeconds(), 0);
- }
-}
-
-static void HighResClockTest(TimeTicks (*GetTicks)()) {
- // IsHighResolution() is false on some systems. Since the product still works
- // even if it's false, it makes this entire test questionable.
- if (!TimeTicks::IsHighResolution())
- return;
-
- // Why do we loop here?
- // We're trying to measure that intervals increment in a VERY small amount
- // of time -- less than 15ms. Unfortunately, if we happen to have a
- // context switch in the middle of our test, the context switch could easily
- // exceed our limit. So, we iterate on this several times. As long as we're
- // able to detect the fine-granularity timers at least once, then the test
- // has succeeded.
-
- const int kTargetGranularityUs = 15000; // 15ms
-
- bool success = false;
- int retries = 100; // Arbitrary.
- TimeDelta delta;
- while (!success && retries--) {
- TimeTicks ticks_start = GetTicks();
- // Loop until we can detect that the clock has changed. Non-HighRes timers
- // will increment in chunks, e.g. 15ms. By spinning until we see a clock
- // change, we detect the minimum time between measurements.
- do {
- delta = GetTicks() - ticks_start;
- } while (delta.InMilliseconds() == 0);
-
- if (delta.InMicroseconds() <= kTargetGranularityUs)
- success = true;
- }
-
- // In high resolution mode, we expect to see the clock increment
- // in intervals less than 15ms.
- EXPECT_TRUE(success);
-}
-
-TEST(TimeTicks, HighRes) {
- HighResClockTest(&TimeTicks::Now);
-}
-
-class TimeTicksOverride {
- public:
- static TimeTicks Now() {
- now_ticks_ += TimeDelta::FromSeconds(1);
- return now_ticks_;
- }
-
- static TimeTicks now_ticks_;
-};
-
-// static
-TimeTicks TimeTicksOverride::now_ticks_;
-
-TEST(TimeTicks, NowOverride) {
- TimeTicksOverride::now_ticks_ = TimeTicks::Min();
-
- // Override is not active. All Now() methods should return a sensible value.
- EXPECT_LT(TimeTicks::Min(), TimeTicks::UnixEpoch());
- EXPECT_LT(TimeTicks::UnixEpoch(), TimeTicks::Now());
- EXPECT_GT(TimeTicks::Max(), TimeTicks::Now());
- EXPECT_LT(TimeTicks::UnixEpoch(), subtle::TimeTicksNowIgnoringOverride());
- EXPECT_GT(TimeTicks::Max(), subtle::TimeTicksNowIgnoringOverride());
-
- {
- // Set override.
- subtle::ScopedTimeClockOverrides overrides(nullptr, &TimeTicksOverride::Now,
- nullptr);
-
- // Overridden value is returned and incremented when Now() is called.
- EXPECT_EQ(TimeTicks::Min() + TimeDelta::FromSeconds(1), TimeTicks::Now());
- EXPECT_EQ(TimeTicks::Min() + TimeDelta::FromSeconds(2), TimeTicks::Now());
-
- // NowIgnoringOverride() still returns real ticks.
- EXPECT_LT(TimeTicks::UnixEpoch(), subtle::TimeTicksNowIgnoringOverride());
- EXPECT_GT(TimeTicks::Max(), subtle::TimeTicksNowIgnoringOverride());
-
- // IgnoringOverride methods didn't call NowOverrideTickClock::NowTicks().
- EXPECT_EQ(TimeTicks::Min() + TimeDelta::FromSeconds(3), TimeTicks::Now());
- }
-
- // All methods return real ticks again.
- EXPECT_LT(TimeTicks::UnixEpoch(), TimeTicks::Now());
- EXPECT_GT(TimeTicks::Max(), TimeTicks::Now());
- EXPECT_LT(TimeTicks::UnixEpoch(), subtle::TimeTicksNowIgnoringOverride());
- EXPECT_GT(TimeTicks::Max(), subtle::TimeTicksNowIgnoringOverride());
-}
-
-class ThreadTicksOverride {
- public:
- static ThreadTicks Now() {
- now_ticks_ += TimeDelta::FromSeconds(1);
- return now_ticks_;
- }
-
- static ThreadTicks now_ticks_;
-};
-
-// static
-ThreadTicks ThreadTicksOverride::now_ticks_;
-
-// IOS doesn't support ThreadTicks::Now().
-#if defined(OS_IOS)
-#define MAYBE_NowOverride DISABLED_NowOverride
-#else
-#define MAYBE_NowOverride NowOverride
-#endif
-TEST(ThreadTicks, MAYBE_NowOverride) {
- ThreadTicksOverride::now_ticks_ = ThreadTicks::Min();
-
- // Override is not active. All Now() methods should return a sensible value.
- ThreadTicks initial_thread_ticks = ThreadTicks::Now();
- EXPECT_LE(initial_thread_ticks, ThreadTicks::Now());
- EXPECT_GT(ThreadTicks::Max(), ThreadTicks::Now());
- EXPECT_LE(initial_thread_ticks, subtle::ThreadTicksNowIgnoringOverride());
- EXPECT_GT(ThreadTicks::Max(), subtle::ThreadTicksNowIgnoringOverride());
-
- {
- // Set override.
- subtle::ScopedTimeClockOverrides overrides(nullptr, nullptr,
- &ThreadTicksOverride::Now);
-
- // Overridden value is returned and incremented when Now() is called.
- EXPECT_EQ(ThreadTicks::Min() + TimeDelta::FromSeconds(1),
- ThreadTicks::Now());
- EXPECT_EQ(ThreadTicks::Min() + TimeDelta::FromSeconds(2),
- ThreadTicks::Now());
-
- // NowIgnoringOverride() still returns real ticks.
- EXPECT_LE(initial_thread_ticks, subtle::ThreadTicksNowIgnoringOverride());
- EXPECT_GT(ThreadTicks::Max(), subtle::ThreadTicksNowIgnoringOverride());
-
- // IgnoringOverride methods didn't call NowOverrideTickClock::NowTicks().
- EXPECT_EQ(ThreadTicks::Min() + TimeDelta::FromSeconds(3),
- ThreadTicks::Now());
- }
-
- // All methods return real ticks again.
- EXPECT_LE(initial_thread_ticks, ThreadTicks::Now());
- EXPECT_GT(ThreadTicks::Max(), ThreadTicks::Now());
- EXPECT_LE(initial_thread_ticks, subtle::ThreadTicksNowIgnoringOverride());
- EXPECT_GT(ThreadTicks::Max(), subtle::ThreadTicksNowIgnoringOverride());
-}
-
-// Fails frequently on Android http://crbug.com/352633 with:
-// Expected: (delta_thread.InMicroseconds()) > (0), actual: 0 vs 0
-#if defined(OS_ANDROID)
-#define MAYBE_ThreadNow DISABLED_ThreadNow
-#else
-#define MAYBE_ThreadNow ThreadNow
-#endif
-TEST(ThreadTicks, MAYBE_ThreadNow) {
- if (ThreadTicks::IsSupported()) {
- ThreadTicks::WaitUntilInitialized();
- TimeTicks begin = TimeTicks::Now();
- ThreadTicks begin_thread = ThreadTicks::Now();
- // Make sure that ThreadNow value is non-zero.
- EXPECT_GT(begin_thread, ThreadTicks());
- // Sleep for 10 milliseconds to get the thread de-scheduled.
- base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(10));
- ThreadTicks end_thread = ThreadTicks::Now();
- TimeTicks end = TimeTicks::Now();
- TimeDelta delta = end - begin;
- TimeDelta delta_thread = end_thread - begin_thread;
- // Make sure that some thread time have elapsed.
- EXPECT_GT(delta_thread.InMicroseconds(), 0);
- // But the thread time is at least 9ms less than clock time.
- TimeDelta difference = delta - delta_thread;
- EXPECT_GE(difference.InMicroseconds(), 9000);
- }
-}
-
-TEST(TimeTicks, SnappedToNextTickBasic) {
- base::TimeTicks phase = base::TimeTicks::FromInternalValue(4000);
- base::TimeDelta interval = base::TimeDelta::FromMicroseconds(1000);
- base::TimeTicks timestamp;
-
- // Timestamp in previous interval.
- timestamp = base::TimeTicks::FromInternalValue(3500);
- EXPECT_EQ(4000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-
- // Timestamp in next interval.
- timestamp = base::TimeTicks::FromInternalValue(4500);
- EXPECT_EQ(5000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-
- // Timestamp multiple intervals before.
- timestamp = base::TimeTicks::FromInternalValue(2500);
- EXPECT_EQ(3000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-
- // Timestamp multiple intervals after.
- timestamp = base::TimeTicks::FromInternalValue(6500);
- EXPECT_EQ(7000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-
- // Timestamp on previous interval.
- timestamp = base::TimeTicks::FromInternalValue(3000);
- EXPECT_EQ(3000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-
- // Timestamp on next interval.
- timestamp = base::TimeTicks::FromInternalValue(5000);
- EXPECT_EQ(5000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-
- // Timestamp equal to phase.
- timestamp = base::TimeTicks::FromInternalValue(4000);
- EXPECT_EQ(4000,
- timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
-}
-
-TEST(TimeTicks, SnappedToNextTickOverflow) {
- // int(big_timestamp / interval) < 0, so this causes a crash if the number of
- // intervals elapsed is attempted to be stored in an int.
- base::TimeTicks phase = base::TimeTicks::FromInternalValue(0);
- base::TimeDelta interval = base::TimeDelta::FromMicroseconds(4000);
- base::TimeTicks big_timestamp =
- base::TimeTicks::FromInternalValue(8635916564000);
-
- EXPECT_EQ(8635916564000,
- big_timestamp.SnappedToNextTick(phase, interval).ToInternalValue());
- EXPECT_EQ(8635916564000,
- big_timestamp.SnappedToNextTick(big_timestamp, interval)
- .ToInternalValue());
-}
-
-#if defined(OS_ANDROID)
-TEST(TimeTicks, Android_FromUptimeMillis_ClocksMatch) {
- JNIEnv* const env = android::AttachCurrentThread();
- android::ScopedJavaLocalRef<jclass> clazz(
- android::GetClass(env, "android/os/SystemClock"));
- ASSERT_TRUE(clazz.obj());
- const jmethodID method_id =
- android::MethodID::Get<android::MethodID::TYPE_STATIC>(
- env, clazz.obj(), "uptimeMillis", "()J");
- ASSERT_FALSE(!method_id);
- // Subtract 1ms from the expected lower bound to allow millisecon-level
- // truncation performed in uptimeMillis().
- const TimeTicks lower_bound_ticks =
- TimeTicks::Now() - TimeDelta::FromMilliseconds(1);
- const TimeTicks converted_ticks = TimeTicks::FromUptimeMillis(
- env->CallStaticLongMethod(clazz.obj(), method_id));
- const TimeTicks upper_bound_ticks = TimeTicks::Now();
- EXPECT_LE(lower_bound_ticks, converted_ticks);
- EXPECT_GE(upper_bound_ticks, converted_ticks);
-}
-#endif // OS_ANDROID
-
-TEST(TimeDelta, FromAndIn) {
- // static_assert also checks that the contained expression is a constant
- // expression, meaning all its components are suitable for initializing global
- // variables.
- static_assert(TimeDelta::FromDays(2) == TimeDelta::FromHours(48), "");
- static_assert(TimeDelta::FromHours(3) == TimeDelta::FromMinutes(180), "");
- static_assert(TimeDelta::FromMinutes(2) == TimeDelta::FromSeconds(120), "");
- static_assert(TimeDelta::FromSeconds(2) == TimeDelta::FromMilliseconds(2000),
- "");
- static_assert(
- TimeDelta::FromMilliseconds(2) == TimeDelta::FromMicroseconds(2000), "");
- static_assert(
- TimeDelta::FromSecondsD(2.3) == TimeDelta::FromMilliseconds(2300), "");
- static_assert(
- TimeDelta::FromMillisecondsD(2.5) == TimeDelta::FromMicroseconds(2500),
- "");
- EXPECT_EQ(TimeDelta::FromDays(13).InDays(), 13);
- EXPECT_EQ(TimeDelta::FromHours(13).InHours(), 13);
- EXPECT_EQ(TimeDelta::FromMinutes(13).InMinutes(), 13);
- EXPECT_EQ(TimeDelta::FromSeconds(13).InSeconds(), 13);
- EXPECT_EQ(TimeDelta::FromSeconds(13).InSecondsF(), 13.0);
- EXPECT_EQ(TimeDelta::FromMilliseconds(13).InMilliseconds(), 13);
- EXPECT_EQ(TimeDelta::FromMilliseconds(13).InMillisecondsF(), 13.0);
- EXPECT_EQ(TimeDelta::FromSecondsD(13.1).InSeconds(), 13);
- EXPECT_EQ(TimeDelta::FromSecondsD(13.1).InSecondsF(), 13.1);
- EXPECT_EQ(TimeDelta::FromMillisecondsD(13.3).InMilliseconds(), 13);
- EXPECT_EQ(TimeDelta::FromMillisecondsD(13.3).InMillisecondsF(), 13.3);
- EXPECT_EQ(TimeDelta::FromMicroseconds(13).InMicroseconds(), 13);
- EXPECT_EQ(TimeDelta::FromMicrosecondsD(13.3).InMicroseconds(), 13);
- EXPECT_EQ(TimeDelta::FromMillisecondsD(3.45678).InMillisecondsF(), 3.456);
- EXPECT_EQ(TimeDelta::FromNanoseconds(12345).InNanoseconds(), 12000);
- EXPECT_EQ(TimeDelta::FromNanosecondsD(12345.678).InNanoseconds(), 12000);
-}
-
-#if defined(OS_POSIX) || defined(OS_FUCHSIA)
-TEST(TimeDelta, TimeSpecConversion) {
- TimeDelta delta = TimeDelta::FromSeconds(0);
- struct timespec result = delta.ToTimeSpec();
- EXPECT_EQ(result.tv_sec, 0);
- EXPECT_EQ(result.tv_nsec, 0);
- EXPECT_EQ(delta, TimeDelta::FromTimeSpec(result));
-
- delta = TimeDelta::FromSeconds(1);
- result = delta.ToTimeSpec();
- EXPECT_EQ(result.tv_sec, 1);
- EXPECT_EQ(result.tv_nsec, 0);
- EXPECT_EQ(delta, TimeDelta::FromTimeSpec(result));
-
- delta = TimeDelta::FromMicroseconds(1);
- result = delta.ToTimeSpec();
- EXPECT_EQ(result.tv_sec, 0);
- EXPECT_EQ(result.tv_nsec, 1000);
- EXPECT_EQ(delta, TimeDelta::FromTimeSpec(result));
-
- delta = TimeDelta::FromMicroseconds(Time::kMicrosecondsPerSecond + 1);
- result = delta.ToTimeSpec();
- EXPECT_EQ(result.tv_sec, 1);
- EXPECT_EQ(result.tv_nsec, 1000);
- EXPECT_EQ(delta, TimeDelta::FromTimeSpec(result));
-}
-#endif // defined(OS_POSIX) || defined(OS_FUCHSIA)
-
-// Our internal time format is serialized in things like databases, so it's
-// important that it's consistent across all our platforms. We use the 1601
-// Windows epoch as the internal format across all platforms.
-TEST(TimeDelta, WindowsEpoch) {
- Time::Exploded exploded;
- exploded.year = 1970;
- exploded.month = 1;
- exploded.day_of_week = 0; // Should be unusued.
- exploded.day_of_month = 1;
- exploded.hour = 0;
- exploded.minute = 0;
- exploded.second = 0;
- exploded.millisecond = 0;
- Time t;
- EXPECT_TRUE(Time::FromUTCExploded(exploded, &t));
- // Unix 1970 epoch.
- EXPECT_EQ(INT64_C(11644473600000000), t.ToInternalValue());
-
- // We can't test 1601 epoch, since the system time functions on Linux
- // only compute years starting from 1900.
-}
-
-// We could define this separately for Time, TimeTicks and TimeDelta but the
-// definitions would be identical anyway.
-template <class Any>
-std::string AnyToString(Any any) {
- std::ostringstream oss;
- oss << any;
- return oss.str();
-}
-
-TEST(TimeDelta, Magnitude) {
- constexpr int64_t zero = 0;
- static_assert(TimeDelta::FromMicroseconds(zero) ==
- TimeDelta::FromMicroseconds(zero).magnitude(),
- "");
-
- constexpr int64_t one = 1;
- constexpr int64_t negative_one = -1;
- static_assert(TimeDelta::FromMicroseconds(one) ==
- TimeDelta::FromMicroseconds(one).magnitude(),
- "");
- static_assert(TimeDelta::FromMicroseconds(one) ==
- TimeDelta::FromMicroseconds(negative_one).magnitude(),
- "");
-
- constexpr int64_t max_int64_minus_one =
- std::numeric_limits<int64_t>::max() - 1;
- constexpr int64_t min_int64_plus_two =
- std::numeric_limits<int64_t>::min() + 2;
- static_assert(
- TimeDelta::FromMicroseconds(max_int64_minus_one) ==
- TimeDelta::FromMicroseconds(max_int64_minus_one).magnitude(),
- "");
- static_assert(TimeDelta::FromMicroseconds(max_int64_minus_one) ==
- TimeDelta::FromMicroseconds(min_int64_plus_two).magnitude(),
- "");
-}
-
-TEST(TimeDelta, ZeroMinMax) {
- constexpr TimeDelta kZero;
- static_assert(kZero.is_zero(), "");
-
- constexpr TimeDelta kMax = TimeDelta::Max();
- static_assert(kMax.is_max(), "");
- static_assert(kMax == TimeDelta::Max(), "");
- static_assert(kMax > TimeDelta::FromDays(100 * 365), "");
- static_assert(kMax > kZero, "");
-
- constexpr TimeDelta kMin = TimeDelta::Min();
- static_assert(kMin.is_min(), "");
- static_assert(kMin == TimeDelta::Min(), "");
- static_assert(kMin < TimeDelta::FromDays(-100 * 365), "");
- static_assert(kMin < kZero, "");
-}
-
-TEST(TimeDelta, MaxConversions) {
- // static_assert also confirms constexpr works as intended.
- constexpr TimeDelta kMax = TimeDelta::Max();
- static_assert(kMax.ToInternalValue() == std::numeric_limits<int64_t>::max(),
- "");
- EXPECT_EQ(kMax.InDays(), std::numeric_limits<int>::max());
- EXPECT_EQ(kMax.InHours(), std::numeric_limits<int>::max());
- EXPECT_EQ(kMax.InMinutes(), std::numeric_limits<int>::max());
- EXPECT_EQ(kMax.InSecondsF(), std::numeric_limits<double>::infinity());
- EXPECT_EQ(kMax.InSeconds(), std::numeric_limits<int64_t>::max());
- EXPECT_EQ(kMax.InMillisecondsF(), std::numeric_limits<double>::infinity());
- EXPECT_EQ(kMax.InMilliseconds(), std::numeric_limits<int64_t>::max());
- EXPECT_EQ(kMax.InMillisecondsRoundedUp(), std::numeric_limits<int64_t>::max());
-
- static_assert(TimeDelta::FromDays(std::numeric_limits<int>::max()).is_max(),
- "");
-
- static_assert(TimeDelta::FromHours(std::numeric_limits<int>::max()).is_max(),
- "");
-
- static_assert(
- TimeDelta::FromMinutes(std::numeric_limits<int>::max()).is_max(), "");
-
- constexpr int64_t max_int = std::numeric_limits<int64_t>::max();
- constexpr int64_t min_int = std::numeric_limits<int64_t>::min();
-
- static_assert(
- TimeDelta::FromSeconds(max_int / Time::kMicrosecondsPerSecond + 1)
- .is_max(),
- "");
-
- static_assert(
- TimeDelta::FromMilliseconds(max_int / Time::kMillisecondsPerSecond + 1)
- .is_max(),
- "");
-
- static_assert(TimeDelta::FromMicroseconds(max_int).is_max(), "");
-
- static_assert(
- TimeDelta::FromSeconds(min_int / Time::kMicrosecondsPerSecond - 1)
- .is_min(),
- "");
-
- static_assert(
- TimeDelta::FromMilliseconds(min_int / Time::kMillisecondsPerSecond - 1)
- .is_min(),
- "");
-
- static_assert(TimeDelta::FromMicroseconds(min_int).is_min(), "");
-
- static_assert(
- TimeDelta::FromMicroseconds(std::numeric_limits<int64_t>::min()).is_min(),
- "");
-
- // Floating point arithmetic resulting in infinity isn't constexpr in C++14.
- EXPECT_TRUE(TimeDelta::FromSecondsD(std::numeric_limits<double>::infinity())
- .is_max());
-
- // Note that max_int/min_int will be rounded when converted to doubles - they
- // can't be exactly represented.
- constexpr double max_d = static_cast<double>(max_int);
- constexpr double min_d = static_cast<double>(min_int);
-
- static_assert(
- TimeDelta::FromSecondsD(max_d / Time::kMicrosecondsPerSecond + 1)
- .is_max(),
- "");
-
- // Floating point arithmetic resulting in infinity isn't constexpr in C++14.
- EXPECT_TRUE(
- TimeDelta::FromMillisecondsD(std::numeric_limits<double>::infinity())
- .is_max());
-
- static_assert(
- TimeDelta::FromMillisecondsD(max_d / Time::kMillisecondsPerSecond * 2)
- .is_max(),
- "");
-
- static_assert(
- TimeDelta::FromSecondsD(min_d / Time::kMicrosecondsPerSecond - 1)
- .is_min(),
- "");
-
- static_assert(
- TimeDelta::FromMillisecondsD(min_d / Time::kMillisecondsPerSecond * 2)
- .is_min(),
- "");
-}
-
-TEST(TimeDelta, NumericOperators) {
- constexpr double d = 0.5;
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (TimeDelta::FromMilliseconds(1000) * d));
- static_assert(TimeDelta::FromMilliseconds(2000) ==
- (TimeDelta::FromMilliseconds(1000) / d),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (TimeDelta::FromMilliseconds(1000) *= d));
- static_assert(TimeDelta::FromMilliseconds(2000) ==
- (TimeDelta::FromMilliseconds(1000) /= d),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (d * TimeDelta::FromMilliseconds(1000)));
-
- constexpr float f = 0.5;
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (TimeDelta::FromMilliseconds(1000) * f));
- static_assert(TimeDelta::FromMilliseconds(2000) ==
- (TimeDelta::FromMilliseconds(1000) / f),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (TimeDelta::FromMilliseconds(1000) *= f));
- static_assert(TimeDelta::FromMilliseconds(2000) ==
- (TimeDelta::FromMilliseconds(1000) /= f),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (f * TimeDelta::FromMilliseconds(1000)));
-
- constexpr int i = 2;
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (TimeDelta::FromMilliseconds(1000) * i));
- static_assert(TimeDelta::FromMilliseconds(500) ==
- (TimeDelta::FromMilliseconds(1000) / i),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (TimeDelta::FromMilliseconds(1000) *= i));
- static_assert(TimeDelta::FromMilliseconds(500) ==
- (TimeDelta::FromMilliseconds(1000) /= i),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (i * TimeDelta::FromMilliseconds(1000)));
-
- constexpr int64_t i64 = 2;
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (TimeDelta::FromMilliseconds(1000) * i64));
- static_assert(TimeDelta::FromMilliseconds(500) ==
- (TimeDelta::FromMilliseconds(1000) / i64),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (TimeDelta::FromMilliseconds(1000) *= i64));
- static_assert(TimeDelta::FromMilliseconds(500) ==
- (TimeDelta::FromMilliseconds(1000) /= i64),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (i64 * TimeDelta::FromMilliseconds(1000)));
-
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (TimeDelta::FromMilliseconds(1000) * 0.5));
- static_assert(TimeDelta::FromMilliseconds(2000) ==
- (TimeDelta::FromMilliseconds(1000) / 0.5),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (TimeDelta::FromMilliseconds(1000) *= 0.5));
- static_assert(TimeDelta::FromMilliseconds(2000) ==
- (TimeDelta::FromMilliseconds(1000) /= 0.5),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(500),
- (0.5 * TimeDelta::FromMilliseconds(1000)));
-
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (TimeDelta::FromMilliseconds(1000) * 2));
- static_assert(TimeDelta::FromMilliseconds(500) ==
- (TimeDelta::FromMilliseconds(1000) / 2),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (TimeDelta::FromMilliseconds(1000) *= 2));
- static_assert(TimeDelta::FromMilliseconds(500) ==
- (TimeDelta::FromMilliseconds(1000) /= 2),
- "");
- EXPECT_EQ(TimeDelta::FromMilliseconds(2000),
- (2 * TimeDelta::FromMilliseconds(1000)));
-}
-
-// Basic test of operators between TimeDeltas (without overflow -- next test
-// handles overflow).
-TEST(TimeDelta, TimeDeltaOperators) {
- constexpr TimeDelta kElevenSeconds = TimeDelta::FromSeconds(11);
- constexpr TimeDelta kThreeSeconds = TimeDelta::FromSeconds(3);
-
- EXPECT_EQ(TimeDelta::FromSeconds(14), kElevenSeconds + kThreeSeconds);
- EXPECT_EQ(TimeDelta::FromSeconds(14), kThreeSeconds + kElevenSeconds);
- EXPECT_EQ(TimeDelta::FromSeconds(8), kElevenSeconds - kThreeSeconds);
- EXPECT_EQ(TimeDelta::FromSeconds(-8), kThreeSeconds - kElevenSeconds);
- static_assert(3 == kElevenSeconds / kThreeSeconds, "");
- static_assert(0 == kThreeSeconds / kElevenSeconds, "");
- static_assert(TimeDelta::FromSeconds(2) == kElevenSeconds % kThreeSeconds,
- "");
-}
-
-TEST(TimeDelta, Overflows) {
- // Some sanity checks. static_assert's used were possible to verify constexpr
- // evaluation at the same time.
- static_assert(TimeDelta::Max().is_max(), "");
- static_assert(-TimeDelta::Max() < TimeDelta(), "");
- static_assert(-TimeDelta::Max() > TimeDelta::Min(), "");
- static_assert(TimeDelta() > -TimeDelta::Max(), "");
-
- TimeDelta large_delta = TimeDelta::Max() - TimeDelta::FromMilliseconds(1);
- TimeDelta large_negative = -large_delta;
- EXPECT_GT(TimeDelta(), large_negative);
- EXPECT_FALSE(large_delta.is_max());
- EXPECT_FALSE((-large_negative).is_min());
- constexpr TimeDelta kOneSecond = TimeDelta::FromSeconds(1);
-
- // Test +, -, * and / operators.
- EXPECT_TRUE((large_delta + kOneSecond).is_max());
- EXPECT_TRUE((large_negative + (-kOneSecond)).is_min());
- EXPECT_TRUE((large_negative - kOneSecond).is_min());
- EXPECT_TRUE((large_delta - (-kOneSecond)).is_max());
- EXPECT_TRUE((large_delta * 2).is_max());
- EXPECT_TRUE((large_delta * -2).is_min());
- EXPECT_TRUE((large_delta / 0.5).is_max());
- EXPECT_TRUE((large_delta / -0.5).is_min());
-
- // Test that double conversions overflow to infinity.
- EXPECT_EQ((large_delta + kOneSecond).InSecondsF(),
- std::numeric_limits<double>::infinity());
- EXPECT_EQ((large_delta + kOneSecond).InMillisecondsF(),
- std::numeric_limits<double>::infinity());
- EXPECT_EQ((large_delta + kOneSecond).InMicrosecondsF(),
- std::numeric_limits<double>::infinity());
-
- // Test +=, -=, *= and /= operators.
- TimeDelta delta = large_delta;
- delta += kOneSecond;
- EXPECT_TRUE(delta.is_max());
- delta = large_negative;
- delta += -kOneSecond;
- EXPECT_TRUE((delta).is_min());
-
- delta = large_negative;
- delta -= kOneSecond;
- EXPECT_TRUE((delta).is_min());
- delta = large_delta;
- delta -= -kOneSecond;
- EXPECT_TRUE(delta.is_max());
-
- delta = large_delta;
- delta *= 2;
- EXPECT_TRUE(delta.is_max());
- delta = large_negative;
- delta *= 1.5;
- EXPECT_TRUE((delta).is_min());
-
- delta = large_delta;
- delta /= 0.5;
- EXPECT_TRUE(delta.is_max());
- delta = large_negative;
- delta /= 0.5;
- EXPECT_TRUE((delta).is_min());
-
- // Test operations with Time and TimeTicks.
- EXPECT_TRUE((large_delta + Time::Now()).is_max());
- EXPECT_TRUE((large_delta + TimeTicks::Now()).is_max());
- EXPECT_TRUE((Time::Now() + large_delta).is_max());
- EXPECT_TRUE((TimeTicks::Now() + large_delta).is_max());
-
- Time time_now = Time::Now();
- EXPECT_EQ(kOneSecond, (time_now + kOneSecond) - time_now);
- EXPECT_EQ(-kOneSecond, (time_now - kOneSecond) - time_now);
-
- TimeTicks ticks_now = TimeTicks::Now();
- EXPECT_EQ(-kOneSecond, (ticks_now - kOneSecond) - ticks_now);
- EXPECT_EQ(kOneSecond, (ticks_now + kOneSecond) - ticks_now);
-}
-
-TEST(TimeDeltaLogging, DCheckEqCompiles) {
- DCHECK_EQ(TimeDelta(), TimeDelta());
-}
-
-TEST(TimeDeltaLogging, EmptyIsZero) {
- constexpr TimeDelta kZero;
- EXPECT_EQ("0 s", AnyToString(kZero));
-}
-
-TEST(TimeDeltaLogging, FiveHundredMs) {
- constexpr TimeDelta kFiveHundredMs = TimeDelta::FromMilliseconds(500);
- EXPECT_EQ("0.5 s", AnyToString(kFiveHundredMs));
-}
-
-TEST(TimeDeltaLogging, MinusTenSeconds) {
- constexpr TimeDelta kMinusTenSeconds = TimeDelta::FromSeconds(-10);
- EXPECT_EQ("-10 s", AnyToString(kMinusTenSeconds));
-}
-
-TEST(TimeDeltaLogging, DoesNotMessUpFormattingFlags) {
- std::ostringstream oss;
- std::ios_base::fmtflags flags_before = oss.flags();
- oss << TimeDelta();
- EXPECT_EQ(flags_before, oss.flags());
-}
-
-TEST(TimeDeltaLogging, DoesNotMakeStreamBad) {
- std::ostringstream oss;
- oss << TimeDelta();
- EXPECT_TRUE(oss.good());
-}
-
-TEST(TimeLogging, DCheckEqCompiles) {
- DCHECK_EQ(Time(), Time());
-}
-
-TEST(TimeLogging, ChromeBirthdate) {
- Time birthdate;
- ASSERT_TRUE(Time::FromString("Tue, 02 Sep 2008 09:42:18 GMT", &birthdate));
- EXPECT_EQ("2008-09-02 09:42:18.000 UTC", AnyToString(birthdate));
-}
-
-TEST(TimeLogging, DoesNotMessUpFormattingFlags) {
- std::ostringstream oss;
- std::ios_base::fmtflags flags_before = oss.flags();
- oss << Time();
- EXPECT_EQ(flags_before, oss.flags());
-}
-
-TEST(TimeLogging, DoesNotMakeStreamBad) {
- std::ostringstream oss;
- oss << Time();
- EXPECT_TRUE(oss.good());
-}
-
-TEST(TimeTicksLogging, DCheckEqCompiles) {
- DCHECK_EQ(TimeTicks(), TimeTicks());
-}
-
-TEST(TimeTicksLogging, ZeroTime) {
- TimeTicks zero;
- EXPECT_EQ("0 bogo-microseconds", AnyToString(zero));
-}
-
-TEST(TimeTicksLogging, FortyYearsLater) {
- TimeTicks forty_years_later =
- TimeTicks() + TimeDelta::FromDays(365.25 * 40);
- EXPECT_EQ("1262304000000000 bogo-microseconds",
- AnyToString(forty_years_later));
-}
-
-TEST(TimeTicksLogging, DoesNotMessUpFormattingFlags) {
- std::ostringstream oss;
- std::ios_base::fmtflags flags_before = oss.flags();
- oss << TimeTicks();
- EXPECT_EQ(flags_before, oss.flags());
-}
-
-TEST(TimeTicksLogging, DoesNotMakeStreamBad) {
- std::ostringstream oss;
- oss << TimeTicks();
- EXPECT_TRUE(oss.good());
-}
-
-} // namespace
-
-} // namespace base
diff --git a/base/time/time_win_unittest.cc b/base/time/time_win_unittest.cc
deleted file mode 100644
index 24cd731..0000000
--- a/base/time/time_win_unittest.cc
+++ /dev/null
@@ -1,365 +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 <windows.h>
-#include <mmsystem.h>
-#include <process.h>
-#include <stdint.h>
-
-#include <cmath>
-#include <limits>
-#include <vector>
-
-#include "base/threading/platform_thread.h"
-#include "base/time/time.h"
-#include "base/win/registry.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace {
-
-// For TimeDelta::ConstexprInitialization
-constexpr int kExpectedDeltaInMilliseconds = 10;
-constexpr TimeDelta kConstexprTimeDelta =
- TimeDelta::FromMilliseconds(kExpectedDeltaInMilliseconds);
-
-class MockTimeTicks : public TimeTicks {
- public:
- static DWORD Ticker() {
- return static_cast<int>(InterlockedIncrement(&ticker_));
- }
-
- static void InstallTicker() {
- old_tick_function_ = SetMockTickFunction(&Ticker);
- ticker_ = -5;
- }
-
- static void UninstallTicker() {
- SetMockTickFunction(old_tick_function_);
- }
-
- private:
- static volatile LONG ticker_;
- static TickFunctionType old_tick_function_;
-};
-
-volatile LONG MockTimeTicks::ticker_;
-MockTimeTicks::TickFunctionType MockTimeTicks::old_tick_function_;
-
-HANDLE g_rollover_test_start;
-
-unsigned __stdcall RolloverTestThreadMain(void* param) {
- int64_t counter = reinterpret_cast<int64_t>(param);
- DWORD rv = WaitForSingleObject(g_rollover_test_start, INFINITE);
- EXPECT_EQ(rv, WAIT_OBJECT_0);
-
- TimeTicks last = TimeTicks::Now();
- for (int index = 0; index < counter; index++) {
- TimeTicks now = TimeTicks::Now();
- int64_t milliseconds = (now - last).InMilliseconds();
- // This is a tight loop; we could have looped faster than our
- // measurements, so the time might be 0 millis.
- EXPECT_GE(milliseconds, 0);
- EXPECT_LT(milliseconds, 250);
- last = now;
- }
- return 0;
-}
-
-} // namespace
-
-// This test spawns many threads, and can occasionally fail due to resource
-// exhaustion in the presence of ASan.
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_WinRollover DISABLED_WinRollover
-#else
-#define MAYBE_WinRollover WinRollover
-#endif
-TEST(TimeTicks, MAYBE_WinRollover) {
- // The internal counter rolls over at ~49days. We'll use a mock
- // timer to test this case.
- // Basic test algorithm:
- // 1) Set clock to rollover - N
- // 2) Create N threads
- // 3) Start the threads
- // 4) Each thread loops through TimeTicks() N times
- // 5) Each thread verifies integrity of result.
-
- const int kThreads = 8;
- // Use int64_t so we can cast into a void* without a compiler warning.
- const int64_t kChecks = 10;
-
- // It takes a lot of iterations to reproduce the bug!
- // (See bug 1081395)
- for (int loop = 0; loop < 4096; loop++) {
- // Setup
- MockTimeTicks::InstallTicker();
- g_rollover_test_start = CreateEvent(0, TRUE, FALSE, 0);
- HANDLE threads[kThreads];
-
- for (int index = 0; index < kThreads; index++) {
- void* argument = reinterpret_cast<void*>(kChecks);
- unsigned thread_id;
- threads[index] = reinterpret_cast<HANDLE>(
- _beginthreadex(NULL, 0, RolloverTestThreadMain, argument, 0,
- &thread_id));
- EXPECT_NE((HANDLE)NULL, threads[index]);
- }
-
- // Start!
- SetEvent(g_rollover_test_start);
-
- // Wait for threads to finish
- for (int index = 0; index < kThreads; index++) {
- DWORD rv = WaitForSingleObject(threads[index], INFINITE);
- EXPECT_EQ(rv, WAIT_OBJECT_0);
- // Since using _beginthreadex() (as opposed to _beginthread),
- // an explicit CloseHandle() is supposed to be called.
- CloseHandle(threads[index]);
- }
-
- CloseHandle(g_rollover_test_start);
-
- // Teardown
- MockTimeTicks::UninstallTicker();
- }
-}
-
-TEST(TimeTicks, SubMillisecondTimers) {
- // IsHighResolution() is false on some systems. Since the product still works
- // even if it's false, it makes this entire test questionable.
- if (!TimeTicks::IsHighResolution())
- return;
-
- const int kRetries = 1000;
- bool saw_submillisecond_timer = false;
-
- // Run kRetries attempts to see a sub-millisecond timer.
- for (int index = 0; index < kRetries; index++) {
- TimeTicks last_time = TimeTicks::Now();
- TimeDelta delta;
- // Spin until the clock has detected a change.
- do {
- delta = TimeTicks::Now() - last_time;
- } while (delta.InMicroseconds() == 0);
- if (delta.InMicroseconds() < 1000) {
- saw_submillisecond_timer = true;
- break;
- }
- }
- EXPECT_TRUE(saw_submillisecond_timer);
-}
-
-TEST(TimeTicks, TimeGetTimeCaps) {
- // Test some basic assumptions that we expect about how timeGetDevCaps works.
-
- TIMECAPS caps;
- MMRESULT status = timeGetDevCaps(&caps, sizeof(caps));
- ASSERT_EQ(static_cast<MMRESULT>(MMSYSERR_NOERROR), status);
-
- EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
- EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
- EXPECT_GE(static_cast<int>(caps.wPeriodMin), 1);
- EXPECT_GT(static_cast<int>(caps.wPeriodMax), 1);
- printf("timeGetTime range is %d to %dms\n", caps.wPeriodMin,
- caps.wPeriodMax);
-}
-
-TEST(TimeTicks, QueryPerformanceFrequency) {
- // Test some basic assumptions that we expect about QPC.
-
- LARGE_INTEGER frequency;
- BOOL rv = QueryPerformanceFrequency(&frequency);
- EXPECT_EQ(TRUE, rv);
- EXPECT_GT(frequency.QuadPart, 1000000); // Expect at least 1MHz
- printf("QueryPerformanceFrequency is %5.2fMHz\n",
- frequency.QuadPart / 1000000.0);
-}
-
-TEST(TimeTicks, TimerPerformance) {
- // Verify that various timer mechanisms can always complete quickly.
- // Note: This is a somewhat arbitrary test.
- const int kLoops = 10000;
-
- typedef TimeTicks (*TestFunc)();
- struct TestCase {
- TestFunc func;
- const char *description;
- };
- // Cheating a bit here: assumes sizeof(TimeTicks) == sizeof(Time)
- // in order to create a single test case list.
- static_assert(sizeof(TimeTicks) == sizeof(Time),
- "TimeTicks and Time must be the same size");
- std::vector<TestCase> cases;
- cases.push_back({reinterpret_cast<TestFunc>(&Time::Now), "Time::Now"});
- cases.push_back({&TimeTicks::Now, "TimeTicks::Now"});
-
- if (ThreadTicks::IsSupported()) {
- ThreadTicks::WaitUntilInitialized();
- cases.push_back(
- {reinterpret_cast<TestFunc>(&ThreadTicks::Now), "ThreadTicks::Now"});
- }
-
- for (const auto& test_case : cases) {
- TimeTicks start = TimeTicks::Now();
- for (int index = 0; index < kLoops; index++)
- test_case.func();
- TimeTicks stop = TimeTicks::Now();
- // Turning off the check for acceptible delays. Without this check,
- // the test really doesn't do much other than measure. But the
- // measurements are still useful for testing timers on various platforms.
- // The reason to remove the check is because the tests run on many
- // buildbots, some of which are VMs. These machines can run horribly
- // slow, and there is really no value for checking against a max timer.
- //const int kMaxTime = 35; // Maximum acceptible milliseconds for test.
- //EXPECT_LT((stop - start).InMilliseconds(), kMaxTime);
- printf("%s: %1.2fus per call\n", test_case.description,
- (stop - start).InMillisecondsF() * 1000 / kLoops);
- }
-}
-
-TEST(TimeTicks, TSCTicksPerSecond) {
- if (ThreadTicks::IsSupported()) {
- ThreadTicks::WaitUntilInitialized();
-
- // Read the CPU frequency from the registry.
- base::win::RegKey processor_key(
- HKEY_LOCAL_MACHINE,
- L"Hardware\\Description\\System\\CentralProcessor\\0", KEY_QUERY_VALUE);
- ASSERT_TRUE(processor_key.Valid());
- DWORD processor_mhz_from_registry;
- ASSERT_EQ(ERROR_SUCCESS,
- processor_key.ReadValueDW(L"~MHz", &processor_mhz_from_registry));
-
- // Expect the measured TSC frequency to be similar to the processor
- // frequency from the registry (0.5% error).
- double tsc_mhz_measured = ThreadTicks::TSCTicksPerSecond() / 1e6;
- EXPECT_NEAR(tsc_mhz_measured, processor_mhz_from_registry,
- 0.005 * processor_mhz_from_registry);
- }
-}
-
-TEST(TimeTicks, FromQPCValue) {
- if (!TimeTicks::IsHighResolution())
- return;
-
- LARGE_INTEGER frequency;
- ASSERT_TRUE(QueryPerformanceFrequency(&frequency));
- const int64_t ticks_per_second = frequency.QuadPart;
- ASSERT_GT(ticks_per_second, 0);
-
- // Generate the tick values to convert, advancing the tick count by varying
- // amounts. These values will ensure that both the fast and overflow-safe
- // conversion logic in FromQPCValue() is tested, and across the entire range
- // of possible QPC tick values.
- std::vector<int64_t> test_cases;
- test_cases.push_back(0);
- const int kNumAdvancements = 100;
- int64_t ticks = 0;
- int64_t ticks_increment = 10;
- for (int i = 0; i < kNumAdvancements; ++i) {
- test_cases.push_back(ticks);
- ticks += ticks_increment;
- ticks_increment = ticks_increment * 6 / 5;
- }
- test_cases.push_back(Time::kQPCOverflowThreshold - 1);
- test_cases.push_back(Time::kQPCOverflowThreshold);
- test_cases.push_back(Time::kQPCOverflowThreshold + 1);
- ticks = Time::kQPCOverflowThreshold + 10;
- ticks_increment = 10;
- for (int i = 0; i < kNumAdvancements; ++i) {
- test_cases.push_back(ticks);
- ticks += ticks_increment;
- ticks_increment = ticks_increment * 6 / 5;
- }
- test_cases.push_back(std::numeric_limits<int64_t>::max());
-
- // Test that the conversions using FromQPCValue() match those computed here
- // using simple floating-point arithmetic. The floating-point math provides
- // enough precision for all reasonable values to confirm that the
- // implementation is correct to the microsecond, and for "very large" values
- // it confirms that the answer is very close to correct.
- for (int64_t ticks : test_cases) {
- const double expected_microseconds_since_origin =
- (static_cast<double>(ticks) * Time::kMicrosecondsPerSecond) /
- ticks_per_second;
- const TimeTicks converted_value = TimeTicks::FromQPCValue(ticks);
- const double converted_microseconds_since_origin =
- static_cast<double>((converted_value - TimeTicks()).InMicroseconds());
- // When we test with very large numbers we end up in a range where adjacent
- // double values are far apart - 512.0 apart in one test failure. In that
- // situation it makes no sense for our epsilon to be 1.0 - it should be
- // the difference between adjacent doubles.
- double epsilon = nextafter(expected_microseconds_since_origin, INFINITY) -
- expected_microseconds_since_origin;
- // Epsilon must be at least 1.0 because converted_microseconds_since_origin
- // comes from an integral value and the rounding is not perfect.
- if (epsilon < 1.0)
- epsilon = 1.0;
- EXPECT_NEAR(expected_microseconds_since_origin,
- converted_microseconds_since_origin, epsilon)
- << "ticks=" << ticks << ", to be converted via logic path: "
- << (ticks < Time::kQPCOverflowThreshold ? "FAST" : "SAFE");
- }
-}
-
-TEST(TimeDelta, ConstexprInitialization) {
- // Make sure that TimeDelta works around crbug.com/635974
- EXPECT_EQ(kExpectedDeltaInMilliseconds, kConstexprTimeDelta.InMilliseconds());
-}
-
-TEST(TimeDelta, FromFileTime) {
- FILETIME ft;
- ft.dwLowDateTime = 1001;
- ft.dwHighDateTime = 0;
-
- // 100100 ns ~= 100 us.
- EXPECT_EQ(TimeDelta::FromMicroseconds(100), TimeDelta::FromFileTime(ft));
-
- ft.dwLowDateTime = 0;
- ft.dwHighDateTime = 1;
-
- // 2^32 * 100 ns ~= 2^32 * 10 us.
- EXPECT_EQ(TimeDelta::FromMicroseconds((1ull << 32) / 10),
- TimeDelta::FromFileTime(ft));
-}
-
-TEST(HighResolutionTimer, GetUsage) {
- EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
-
- Time::ResetHighResolutionTimerUsage();
-
- // 0% usage since the timer isn't activated regardless of how much time has
- // elapsed.
- EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
- Sleep(10);
- EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
-
- Time::ActivateHighResolutionTimer(true);
- Time::ResetHighResolutionTimerUsage();
-
- Sleep(20);
- // 100% usage since the timer has been activated entire time.
- EXPECT_EQ(100.0, Time::GetHighResolutionTimerUsage());
-
- Time::ActivateHighResolutionTimer(false);
- Sleep(20);
- double usage1 = Time::GetHighResolutionTimerUsage();
- // usage1 should be about 50%.
- EXPECT_LT(usage1, 100.0);
- EXPECT_GT(usage1, 0.0);
-
- Time::ActivateHighResolutionTimer(true);
- Sleep(10);
- Time::ActivateHighResolutionTimer(false);
- double usage2 = Time::GetHighResolutionTimerUsage();
- // usage2 should be about 60%.
- EXPECT_LT(usage2, 100.0);
- EXPECT_GT(usage2, usage1);
-
- Time::ResetHighResolutionTimerUsage();
- EXPECT_EQ(0.0, Time::GetHighResolutionTimerUsage());
-}
-
-} // namespace base
diff --git a/base/timer/hi_res_timer_manager_unittest.cc b/base/timer/hi_res_timer_manager_unittest.cc
deleted file mode 100644
index 3860c09..0000000
--- a/base/timer/hi_res_timer_manager_unittest.cc
+++ /dev/null
@@ -1,62 +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/timer/hi_res_timer_manager.h"
-
-#include <memory>
-#include <utility>
-
-#include "base/power_monitor/power_monitor.h"
-#include "base/power_monitor/power_monitor_device_source.h"
-#include "base/test/scoped_task_environment.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-#if defined(OS_WIN)
-TEST(HiResTimerManagerTest, ToggleOnOff) {
- // The power monitor creates Window to receive power notifications from
- // Windows, which makes this test flaky if you run while the machine
- // goes in or out of AC power.
- test::ScopedTaskEnvironment scoped_task_environment(
- test::ScopedTaskEnvironment::MainThreadType::UI);
- std::unique_ptr<base::PowerMonitorSource> power_monitor_source(
- new base::PowerMonitorDeviceSource());
- std::unique_ptr<base::PowerMonitor> power_monitor(
- new base::PowerMonitor(std::move(power_monitor_source)));
-
- HighResolutionTimerManager manager;
- // Simulate a on-AC power event to get to a known initial state.
- manager.OnPowerStateChange(false);
-
- // Loop a few times to test power toggling.
- for (int times = 0; times != 3; ++times) {
- // The manager has the high resolution clock enabled now.
- EXPECT_TRUE(manager.hi_res_clock_available());
- // But the Time class has it off, because it hasn't been activated.
- EXPECT_FALSE(base::Time::IsHighResolutionTimerInUse());
-
- // Activate the high resolution timer.
- base::Time::ActivateHighResolutionTimer(true);
- EXPECT_TRUE(base::Time::IsHighResolutionTimerInUse());
-
- // Simulate a on-battery power event.
- manager.OnPowerStateChange(true);
- EXPECT_FALSE(manager.hi_res_clock_available());
- EXPECT_FALSE(base::Time::IsHighResolutionTimerInUse());
-
- // Back to on-AC power.
- manager.OnPowerStateChange(false);
- EXPECT_TRUE(manager.hi_res_clock_available());
- EXPECT_TRUE(base::Time::IsHighResolutionTimerInUse());
-
- // De-activate the high resolution timer.
- base::Time::ActivateHighResolutionTimer(false);
- }
-}
-#endif // defined(OS_WIN)
-
-} // namespace base
diff --git a/base/timer/mock_timer_unittest.cc b/base/timer/mock_timer_unittest.cc
deleted file mode 100644
index 61716a4..0000000
--- a/base/timer/mock_timer_unittest.cc
+++ /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.
-
-#include "base/timer/mock_timer.h"
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-void CallMeMaybe(int *number) {
- (*number)++;
-}
-
-TEST(MockTimerTest, FiresOnce) {
- int calls = 0;
- base::MockTimer timer(false, false);
- base::TimeDelta delay = base::TimeDelta::FromSeconds(2);
- timer.Start(FROM_HERE, delay,
- base::Bind(&CallMeMaybe,
- base::Unretained(&calls)));
- EXPECT_EQ(delay, timer.GetCurrentDelay());
- EXPECT_TRUE(timer.IsRunning());
- timer.Fire();
- EXPECT_FALSE(timer.IsRunning());
- EXPECT_EQ(1, calls);
-}
-
-TEST(MockTimerTest, FiresRepeatedly) {
- int calls = 0;
- base::MockTimer timer(true, true);
- base::TimeDelta delay = base::TimeDelta::FromSeconds(2);
- timer.Start(FROM_HERE, delay,
- base::Bind(&CallMeMaybe,
- base::Unretained(&calls)));
- timer.Fire();
- EXPECT_TRUE(timer.IsRunning());
- timer.Fire();
- timer.Fire();
- EXPECT_TRUE(timer.IsRunning());
- EXPECT_EQ(3, calls);
-}
-
-TEST(MockTimerTest, Stops) {
- int calls = 0;
- base::MockTimer timer(true, true);
- base::TimeDelta delay = base::TimeDelta::FromSeconds(2);
- timer.Start(FROM_HERE, delay,
- base::Bind(&CallMeMaybe,
- base::Unretained(&calls)));
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
-}
-
-class HasWeakPtr : public base::SupportsWeakPtr<HasWeakPtr> {
- public:
- HasWeakPtr() = default;
- virtual ~HasWeakPtr() = default;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(HasWeakPtr);
-};
-
-TEST(MockTimerTest, DoesNotRetainClosure) {
- HasWeakPtr *has_weak_ptr = new HasWeakPtr();
- base::WeakPtr<HasWeakPtr> weak_ptr(has_weak_ptr->AsWeakPtr());
- base::MockTimer timer(false, false);
- base::TimeDelta delay = base::TimeDelta::FromSeconds(2);
- ASSERT_TRUE(weak_ptr.get());
- timer.Start(FROM_HERE, delay,
- base::Bind(base::DoNothing::Repeatedly<HasWeakPtr*>(),
- base::Owned(has_weak_ptr)));
- ASSERT_TRUE(weak_ptr.get());
- timer.Fire();
- ASSERT_FALSE(weak_ptr.get());
-}
-
-} // namespace
diff --git a/base/timer/timer_unittest.cc b/base/timer/timer_unittest.cc
deleted file mode 100644
index ae587bf..0000000
--- a/base/timer/timer_unittest.cc
+++ /dev/null
@@ -1,904 +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/timer/timer.h"
-
-#include <stddef.h>
-
-#include <memory>
-
-#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/message_loop/message_loop.h"
-#include "base/run_loop.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_mock_time_task_runner.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/sequenced_task_runner_handle.h"
-#include "base/threading/thread.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-// The message loops on which each 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
-};
-
-const int kNumTestingMessageLoops = arraysize(testing_message_loops);
-
-class Receiver {
- public:
- Receiver() : count_(0) {}
- void OnCalled() { count_++; }
- bool WasCalled() { return count_ > 0; }
- int TimesCalled() { return count_; }
-
- private:
- int count_;
-};
-
-// A basic helper class that can start a one-shot timer and signal a
-// WaitableEvent when this timer fires.
-class OneShotTimerTesterBase {
- public:
- // |did_run|, if provided, will be signaled when Run() fires.
- explicit OneShotTimerTesterBase(
- WaitableEvent* did_run = nullptr,
- const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
- : did_run_(did_run), delay_(delay) {}
-
- virtual ~OneShotTimerTesterBase() = default;
-
- void Start() {
- started_time_ = TimeTicks::Now();
- timer_->Start(FROM_HERE, delay_, this, &OneShotTimerTesterBase::Run);
- }
-
- bool IsRunning() { return timer_->IsRunning(); }
-
- TimeTicks started_time() const { return started_time_; }
- TimeDelta delay() const { return delay_; }
-
- protected:
- virtual void Run() {
- if (did_run_) {
- EXPECT_FALSE(did_run_->IsSignaled());
- did_run_->Signal();
- }
- }
-
- std::unique_ptr<OneShotTimer> timer_ = std::make_unique<OneShotTimer>();
-
- private:
- WaitableEvent* const did_run_;
- const TimeDelta delay_;
- TimeTicks started_time_;
-
- DISALLOW_COPY_AND_ASSIGN(OneShotTimerTesterBase);
-};
-
-// Extends functionality of OneShotTimerTesterBase with the abilities to wait
-// until the timer fires and to change task runner for the timer.
-class OneShotTimerTester : public OneShotTimerTesterBase {
- public:
- // |did_run|, if provided, will be signaled when Run() fires.
- explicit OneShotTimerTester(
- WaitableEvent* did_run = nullptr,
- const TimeDelta& delay = TimeDelta::FromMilliseconds(10))
- : OneShotTimerTesterBase(did_run, delay),
- quit_closure_(run_loop_.QuitClosure()) {}
-
- ~OneShotTimerTester() override = default;
-
- void SetTaskRunner(scoped_refptr<SequencedTaskRunner> task_runner) {
- timer_->SetTaskRunner(std::move(task_runner));
-
- // Run() will be invoked on |task_runner| but |run_loop_|'s QuitClosure
- // needs to run on this thread (where the MessageLoop lives).
- quit_closure_ = Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
- SequencedTaskRunnerHandle::Get(), FROM_HERE,
- run_loop_.QuitClosure());
- }
-
- // Blocks until Run() executes and confirms that Run() didn't fire before
- // |delay_| expired.
- void WaitAndConfirmTimerFiredAfterDelay() {
- run_loop_.Run();
-
- EXPECT_NE(TimeTicks(), started_time());
- EXPECT_GE(TimeTicks::Now() - started_time(), delay());
- }
-
- protected:
- // Overridable method to do things on Run() before signaling events/closures
- // managed by this helper.
- virtual void OnRun() {}
-
- private:
- void Run() override {
- OnRun();
- OneShotTimerTesterBase::Run();
- quit_closure_.Run();
- }
-
- RunLoop run_loop_;
- Closure quit_closure_;
-
- DISALLOW_COPY_AND_ASSIGN(OneShotTimerTester);
-};
-
-class OneShotSelfDeletingTimerTester : public OneShotTimerTester {
- protected:
- void OnRun() override { timer_.reset(); }
-};
-
-constexpr int kNumRepeats = 10;
-
-class RepeatingTimerTester {
- public:
- explicit RepeatingTimerTester(WaitableEvent* did_run, const TimeDelta& delay)
- : counter_(kNumRepeats),
- quit_closure_(run_loop_.QuitClosure()),
- did_run_(did_run),
- delay_(delay) {}
-
- void Start() {
- started_time_ = TimeTicks::Now();
- timer_.Start(FROM_HERE, delay_, this, &RepeatingTimerTester::Run);
- }
-
- void WaitAndConfirmTimerFiredRepeatedlyAfterDelay() {
- run_loop_.Run();
-
- EXPECT_NE(TimeTicks(), started_time_);
- EXPECT_GE(TimeTicks::Now() - started_time_, kNumRepeats * delay_);
- }
-
- private:
- void Run() {
- if (--counter_ == 0) {
- if (did_run_) {
- EXPECT_FALSE(did_run_->IsSignaled());
- did_run_->Signal();
- }
- timer_.Stop();
- quit_closure_.Run();
- }
- }
-
- RepeatingTimer timer_;
- int counter_;
-
- RunLoop run_loop_;
- Closure quit_closure_;
- WaitableEvent* const did_run_;
-
- const TimeDelta delay_;
- TimeTicks started_time_;
-
- DISALLOW_COPY_AND_ASSIGN(RepeatingTimerTester);
-};
-
-// Basic test with same setup as RunTest_OneShotTimers_Cancel below to confirm
-// that |did_run_a| would be signaled in that test if it wasn't for the
-// deletion.
-void RunTest_OneShotTimers(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- OneShotTimerTester a(&did_run_a);
- a.Start();
-
- OneShotTimerTester b;
- b.Start();
-
- b.WaitAndConfirmTimerFiredAfterDelay();
-
- EXPECT_TRUE(did_run_a.IsSignaled());
-}
-
-void RunTest_OneShotTimers_Cancel(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- OneShotTimerTester* a = new OneShotTimerTester(&did_run_a);
-
- // This should run before the timer expires.
- SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
-
- // Now start the timer.
- a->Start();
-
- OneShotTimerTester b;
- b.Start();
-
- b.WaitAndConfirmTimerFiredAfterDelay();
-
- EXPECT_FALSE(did_run_a.IsSignaled());
-}
-
-void RunTest_OneShotSelfDeletingTimer(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- OneShotSelfDeletingTimerTester f;
- f.Start();
- f.WaitAndConfirmTimerFiredAfterDelay();
-}
-
-void RunTest_RepeatingTimer(MessageLoop::Type message_loop_type,
- const TimeDelta& delay) {
- MessageLoop loop(message_loop_type);
-
- RepeatingTimerTester f(nullptr, delay);
- f.Start();
- f.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
-}
-
-void RunTest_RepeatingTimer_Cancel(MessageLoop::Type message_loop_type,
- const TimeDelta& delay) {
- MessageLoop loop(message_loop_type);
-
- WaitableEvent did_run_a(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- RepeatingTimerTester* a = new RepeatingTimerTester(&did_run_a, delay);
-
- // This should run before the timer expires.
- SequencedTaskRunnerHandle::Get()->DeleteSoon(FROM_HERE, a);
-
- // Now start the timer.
- a->Start();
-
- RepeatingTimerTester b(nullptr, delay);
- b.Start();
-
- b.WaitAndConfirmTimerFiredRepeatedlyAfterDelay();
-
- // |a| should not have fired despite |b| starting after it on the same
- // sequence and being complete by now.
- EXPECT_FALSE(did_run_a.IsSignaled());
-}
-
-class DelayTimerTarget {
- public:
- bool signaled() const { return signaled_; }
-
- void Signal() {
- ASSERT_FALSE(signaled_);
- signaled_ = true;
- }
-
- private:
- bool signaled_ = false;
-};
-
-void RunTest_DelayTimer_NoCall(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- // If Delay is never called, the timer shouldn't go off.
- DelayTimerTarget target;
- DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
- &DelayTimerTarget::Signal);
-
- OneShotTimerTester tester;
- tester.Start();
- tester.WaitAndConfirmTimerFiredAfterDelay();
-
- ASSERT_FALSE(target.signaled());
-}
-
-void RunTest_DelayTimer_OneCall(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- DelayTimerTarget target;
- DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(1), &target,
- &DelayTimerTarget::Signal);
- timer.Reset();
-
- OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(100));
- tester.Start();
- tester.WaitAndConfirmTimerFiredAfterDelay();
-
- ASSERT_TRUE(target.signaled());
-}
-
-struct ResetHelper {
- ResetHelper(DelayTimer* timer, DelayTimerTarget* target)
- : timer_(timer), target_(target) {}
-
- void Reset() {
- ASSERT_FALSE(target_->signaled());
- timer_->Reset();
- }
-
- private:
- DelayTimer* const timer_;
- DelayTimerTarget* const target_;
-};
-
-void RunTest_DelayTimer_Reset(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- // If Delay is never called, the timer shouldn't go off.
- DelayTimerTarget target;
- DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
- &DelayTimerTarget::Signal);
- timer.Reset();
-
- ResetHelper reset_helper(&timer, &target);
-
- OneShotTimer timers[20];
- for (size_t i = 0; i < arraysize(timers); ++i) {
- timers[i].Start(FROM_HERE, TimeDelta::FromMilliseconds(i * 10),
- &reset_helper, &ResetHelper::Reset);
- }
-
- OneShotTimerTester tester(nullptr, TimeDelta::FromMilliseconds(300));
- tester.Start();
- tester.WaitAndConfirmTimerFiredAfterDelay();
-
- ASSERT_TRUE(target.signaled());
-}
-
-class DelayTimerFatalTarget {
- public:
- void Signal() {
- ASSERT_TRUE(false);
- }
-};
-
-void RunTest_DelayTimer_Deleted(MessageLoop::Type message_loop_type) {
- MessageLoop loop(message_loop_type);
-
- DelayTimerFatalTarget target;
-
- {
- DelayTimer timer(FROM_HERE, TimeDelta::FromMilliseconds(50), &target,
- &DelayTimerFatalTarget::Signal);
- timer.Reset();
- }
-
- // When the timer is deleted, the DelayTimerFatalTarget should never be
- // called.
- PlatformThread::Sleep(TimeDelta::FromMilliseconds(100));
-}
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-// Each test is run against each type of MessageLoop. That way we are sure
-// that timers work properly in all configurations.
-
-TEST(TimerTest, OneShotTimers) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_OneShotTimers(testing_message_loops[i]);
- }
-}
-
-TEST(TimerTest, OneShotTimers_Cancel) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_OneShotTimers_Cancel(testing_message_loops[i]);
- }
-}
-
-// If underline timer does not handle properly, we will crash or fail
-// in full page heap environment.
-TEST(TimerTest, OneShotSelfDeletingTimer) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_OneShotSelfDeletingTimer(testing_message_loops[i]);
- }
-}
-
-TEST(TimerTest, OneShotTimer_CustomTaskRunner) {
- // A MessageLoop is required for the timer events on the other thread to
- // communicate back to the Timer under test.
- MessageLoop loop;
-
- Thread other_thread("OneShotTimer_CustomTaskRunner");
- other_thread.Start();
-
- WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- OneShotTimerTester f(&did_run);
- f.SetTaskRunner(other_thread.task_runner());
- f.Start();
- EXPECT_TRUE(f.IsRunning() || did_run.IsSignaled());
-
- f.WaitAndConfirmTimerFiredAfterDelay();
- EXPECT_TRUE(did_run.IsSignaled());
-
- // |f| should already have communicated back to this |loop| before invoking
- // Run() and as such this thread should already be aware that |f| is no longer
- // running.
- EXPECT_TRUE(loop.IsIdleForTesting());
- EXPECT_FALSE(f.IsRunning());
-}
-
-TEST(TimerTest, OneShotTimerWithTickClock) {
- scoped_refptr<TestMockTimeTaskRunner> task_runner(
- new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
- MessageLoop message_loop;
- message_loop.SetTaskRunner(task_runner);
- Receiver receiver;
- OneShotTimer timer(task_runner->GetMockTickClock());
- timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
- Bind(&Receiver::OnCalled, Unretained(&receiver)));
- task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
- EXPECT_TRUE(receiver.WasCalled());
-}
-
-TEST(TimerTest, RepeatingTimer) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_RepeatingTimer(testing_message_loops[i],
- TimeDelta::FromMilliseconds(10));
- }
-}
-
-TEST(TimerTest, RepeatingTimer_Cancel) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
- TimeDelta::FromMilliseconds(10));
- }
-}
-
-TEST(TimerTest, RepeatingTimerZeroDelay) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_RepeatingTimer(testing_message_loops[i],
- TimeDelta::FromMilliseconds(0));
- }
-}
-
-TEST(TimerTest, RepeatingTimerZeroDelay_Cancel) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_RepeatingTimer_Cancel(testing_message_loops[i],
- TimeDelta::FromMilliseconds(0));
- }
-}
-
-TEST(TimerTest, RepeatingTimerWithTickClock) {
- scoped_refptr<TestMockTimeTaskRunner> task_runner(
- new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
- MessageLoop message_loop;
- message_loop.SetTaskRunner(task_runner);
- Receiver receiver;
- const int expected_times_called = 10;
- RepeatingTimer timer(task_runner->GetMockTickClock());
- timer.Start(FROM_HERE, TimeDelta::FromSeconds(1),
- Bind(&Receiver::OnCalled, Unretained(&receiver)));
- task_runner->FastForwardBy(TimeDelta::FromSeconds(expected_times_called));
- timer.Stop();
- EXPECT_EQ(expected_times_called, receiver.TimesCalled());
-}
-
-TEST(TimerTest, DelayTimer_NoCall) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_DelayTimer_NoCall(testing_message_loops[i]);
- }
-}
-
-TEST(TimerTest, DelayTimer_OneCall) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_DelayTimer_OneCall(testing_message_loops[i]);
- }
-}
-
-// It's flaky on the buildbot, http://crbug.com/25038.
-TEST(TimerTest, DISABLED_DelayTimer_Reset) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_DelayTimer_Reset(testing_message_loops[i]);
- }
-}
-
-TEST(TimerTest, DelayTimer_Deleted) {
- for (int i = 0; i < kNumTestingMessageLoops; i++) {
- RunTest_DelayTimer_Deleted(testing_message_loops[i]);
- }
-}
-
-TEST(TimerTest, DelayTimerWithTickClock) {
- scoped_refptr<TestMockTimeTaskRunner> task_runner(
- new TestMockTimeTaskRunner(Time::Now(), TimeTicks::Now()));
- MessageLoop message_loop;
- message_loop.SetTaskRunner(task_runner);
- Receiver receiver;
- DelayTimer timer(FROM_HERE, TimeDelta::FromSeconds(1), &receiver,
- &Receiver::OnCalled, task_runner->GetMockTickClock());
- task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
- EXPECT_FALSE(receiver.WasCalled());
- timer.Reset();
- task_runner->FastForwardBy(TimeDelta::FromMilliseconds(999));
- EXPECT_FALSE(receiver.WasCalled());
- timer.Reset();
- task_runner->FastForwardBy(TimeDelta::FromSeconds(1));
- EXPECT_TRUE(receiver.WasCalled());
-}
-
-TEST(TimerTest, 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.
- WaitableEvent did_run(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- {
- OneShotTimerTesterBase a(&did_run);
- OneShotTimerTesterBase b(&did_run);
- OneShotTimerTesterBase c(&did_run);
- OneShotTimerTesterBase d(&did_run);
- {
- MessageLoop loop;
- a.Start();
- b.Start();
- } // MessageLoop destructs by falling out of scope.
- } // OneShotTimers destruct. SHOULD NOT CRASH, of course.
-
- EXPECT_FALSE(did_run.IsSignaled());
-}
-
-// Ref counted class which owns a Timer. The class passes a reference to itself
-// via the |user_task| parameter in Timer::Start(). |Timer::user_task_| might
-// end up holding the last reference to the class.
-class OneShotSelfOwningTimerTester
- : public RefCounted<OneShotSelfOwningTimerTester> {
- public:
- OneShotSelfOwningTimerTester() = default;
-
- void StartTimer() {
- // Start timer with long delay in order to test the timer getting destroyed
- // while a timer task is still pending.
- timer_.Start(FROM_HERE, TimeDelta::FromDays(1),
- base::Bind(&OneShotSelfOwningTimerTester::Run, this));
- }
-
- private:
- friend class RefCounted<OneShotSelfOwningTimerTester>;
- ~OneShotSelfOwningTimerTester() = default;
-
- void Run() {
- ADD_FAILURE() << "Timer unexpectedly fired.";
- }
-
- OneShotTimer timer_;
-
- DISALLOW_COPY_AND_ASSIGN(OneShotSelfOwningTimerTester);
-};
-
-TEST(TimerTest, MessageLoopShutdownSelfOwningTimer) {
- // This test verifies that shutdown of the message loop does not cause crashes
- // if there is a pending timer not yet fired and |Timer::user_task_| owns the
- // timer. The test may only trigger exceptions if debug heap checking is
- // enabled.
-
- MessageLoop loop;
- scoped_refptr<OneShotSelfOwningTimerTester> tester =
- new OneShotSelfOwningTimerTester();
-
- std::move(tester)->StartTimer();
- // |Timer::user_task_| owns sole reference to |tester|.
-
- // MessageLoop destructs by falling out of scope. SHOULD NOT CRASH.
-}
-
-void TimerTestCallback() {
-}
-
-TEST(TimerTest, NonRepeatIsRunning) {
- {
- MessageLoop loop;
- Timer timer(false, false);
- EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
- EXPECT_TRUE(timer.user_task().is_null());
- }
-
- {
- Timer timer(true, false);
- MessageLoop loop;
- EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
- ASSERT_FALSE(timer.user_task().is_null());
- timer.Reset();
- EXPECT_TRUE(timer.IsRunning());
- }
-}
-
-TEST(TimerTest, NonRepeatMessageLoopDeath) {
- Timer timer(false, false);
- {
- MessageLoop loop;
- EXPECT_FALSE(timer.IsRunning());
- timer.Start(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback));
- EXPECT_TRUE(timer.IsRunning());
- }
- EXPECT_FALSE(timer.IsRunning());
- EXPECT_TRUE(timer.user_task().is_null());
-}
-
-TEST(TimerTest, RetainRepeatIsRunning) {
- MessageLoop loop;
- Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
- true);
- EXPECT_FALSE(timer.IsRunning());
- timer.Reset();
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
- timer.Reset();
- EXPECT_TRUE(timer.IsRunning());
-}
-
-TEST(TimerTest, RetainNonRepeatIsRunning) {
- MessageLoop loop;
- Timer timer(FROM_HERE, TimeDelta::FromDays(1), Bind(&TimerTestCallback),
- false);
- EXPECT_FALSE(timer.IsRunning());
- timer.Reset();
- EXPECT_TRUE(timer.IsRunning());
- timer.Stop();
- EXPECT_FALSE(timer.IsRunning());
- timer.Reset();
- 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() {
- g_callback_happened1 = true;
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-void SetCallbackHappened2() {
- g_callback_happened2 = true;
- RunLoop::QuitCurrentWhenIdleDeprecated();
-}
-
-} // namespace
-
-TEST(TimerTest, ContinuationStopStart) {
- {
- ClearAllCallbackHappened();
- MessageLoop loop;
- Timer timer(false, false);
- timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
- Bind(&SetCallbackHappened1));
- timer.Stop();
- timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(40),
- Bind(&SetCallbackHappened2));
- RunLoop().Run();
- EXPECT_FALSE(g_callback_happened1);
- EXPECT_TRUE(g_callback_happened2);
- }
-}
-
-TEST(TimerTest, ContinuationReset) {
- {
- ClearAllCallbackHappened();
- MessageLoop loop;
- Timer timer(false, false);
- timer.Start(FROM_HERE, TimeDelta::FromMilliseconds(10),
- Bind(&SetCallbackHappened1));
- timer.Reset();
- // Since Reset happened before task ran, the user_task must not be cleared:
- ASSERT_FALSE(timer.user_task().is_null());
- RunLoop().Run();
- EXPECT_TRUE(g_callback_happened1);
- }
-}
-
-namespace {
-
-// Fixture for tests requiring ScopedTaskEnvironment. Includes a WaitableEvent
-// so that cases may Wait() on one thread and Signal() (explicitly, or
-// implicitly via helper methods) on another.
-class TimerSequenceTest : public testing::Test {
- public:
- TimerSequenceTest()
- : event_(WaitableEvent::ResetPolicy::AUTOMATIC,
- WaitableEvent::InitialState::NOT_SIGNALED) {}
-
- // Block until Signal() is called on another thread.
- void Wait() { event_.Wait(); }
-
- void Signal() { event_.Signal(); }
-
- // Helper to augment a task with a subsequent call to Signal().
- Closure TaskWithSignal(const Closure& task) {
- return Bind(&TimerSequenceTest::RunTaskAndSignal, Unretained(this), task);
- }
-
- // Create the timer.
- void CreateTimer() { timer_.reset(new OneShotTimer); }
-
- // Schedule an event on the timer.
- void StartTimer(TimeDelta delay, const Closure& task) {
- timer_->Start(FROM_HERE, delay, task);
- }
-
- void SetTaskRunnerForTimer(scoped_refptr<SequencedTaskRunner> task_runner) {
- timer_->SetTaskRunner(std::move(task_runner));
- }
-
- // Tell the timer to abandon the task.
- void AbandonTask() {
- EXPECT_TRUE(timer_->IsRunning());
- // Reset() to call Timer::AbandonScheduledTask()
- timer_->Reset();
- EXPECT_TRUE(timer_->IsRunning());
- timer_->Stop();
- EXPECT_FALSE(timer_->IsRunning());
- }
-
- static void VerifyAffinity(const SequencedTaskRunner* task_runner) {
- EXPECT_TRUE(task_runner->RunsTasksInCurrentSequence());
- }
-
- // Delete the timer.
- void DeleteTimer() { timer_.reset(); }
-
- private:
- void RunTaskAndSignal(const Closure& task) {
- task.Run();
- Signal();
- }
-
- base::test::ScopedTaskEnvironment scoped_task_environment_;
- WaitableEvent event_;
- std::unique_ptr<OneShotTimer> timer_;
-
- DISALLOW_COPY_AND_ASSIGN(TimerSequenceTest);
-};
-
-} // namespace
-
-TEST_F(TimerSequenceTest, OneShotTimerTaskOnPoolSequence) {
- scoped_refptr<SequencedTaskRunner> task_runner =
- base::CreateSequencedTaskRunnerWithTraits({});
-
- base::RunLoop run_loop_;
-
- // Timer is created on this thread.
- CreateTimer();
-
- // Task will execute on a pool thread.
- SetTaskRunnerForTimer(task_runner);
- StartTimer(TimeDelta::FromMilliseconds(1),
- Bind(IgnoreResult(&SequencedTaskRunner::PostTask),
- SequencedTaskRunnerHandle::Get(), FROM_HERE,
- run_loop_.QuitClosure()));
-
- // Spin the loop so that the delayed task fires on it, which will forward it
- // to |task_runner|. And since the Timer's task is one that posts back to this
- // MessageLoop to quit, we finally unblock.
- run_loop_.Run();
-
- // Timer will be destroyed on this thread.
- DeleteTimer();
-}
-
-TEST_F(TimerSequenceTest, OneShotTimerUsedOnPoolSequence) {
- scoped_refptr<SequencedTaskRunner> task_runner =
- base::CreateSequencedTaskRunnerWithTraits({});
-
- // Timer is created on this thread.
- CreateTimer();
-
- // Task will be scheduled from a pool thread.
- task_runner->PostTask(
- FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
- TimeDelta::FromMilliseconds(1),
- Bind(&TimerSequenceTest::Signal, Unretained(this))));
- Wait();
-
- // Timer must be destroyed on pool thread, too.
- task_runner->PostTask(
- FROM_HERE,
- TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
- Wait();
-}
-
-TEST_F(TimerSequenceTest, OneShotTimerTwoSequencesAbandonTask) {
- scoped_refptr<SequencedTaskRunner> task_runner1 =
- base::CreateSequencedTaskRunnerWithTraits({});
- scoped_refptr<SequencedTaskRunner> task_runner2 =
- base::CreateSequencedTaskRunnerWithTraits({});
-
- // Create timer on sequence #1.
- task_runner1->PostTask(
- FROM_HERE,
- TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
- Wait();
-
- // And tell it to execute on a different sequence (#2).
- task_runner1->PostTask(
- FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
- Unretained(this), task_runner2)));
- Wait();
-
- // Task will be scheduled from sequence #1.
- task_runner1->PostTask(
- FROM_HERE, BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
- TimeDelta::FromHours(1), DoNothing()));
-
- // Abandon task - must be called from scheduling sequence (#1).
- task_runner1->PostTask(
- FROM_HERE,
- TaskWithSignal(Bind(&TimerSequenceTest::AbandonTask, Unretained(this))));
- Wait();
-
- // Timer must be destroyed on the sequence it was scheduled from (#1).
- task_runner1->PostTask(
- FROM_HERE,
- TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
- Wait();
-}
-
-TEST_F(TimerSequenceTest, OneShotTimerUsedAndTaskedOnDifferentSequences) {
- scoped_refptr<SequencedTaskRunner> task_runner1 =
- base::CreateSequencedTaskRunnerWithTraits({});
- scoped_refptr<SequencedTaskRunner> task_runner2 =
- base::CreateSequencedTaskRunnerWithTraits({});
-
- // Create timer on sequence #1.
- task_runner1->PostTask(
- FROM_HERE,
- TaskWithSignal(Bind(&TimerSequenceTest::CreateTimer, Unretained(this))));
- Wait();
-
- // And tell it to execute on a different sequence (#2).
- task_runner1->PostTask(
- FROM_HERE, TaskWithSignal(Bind(&TimerSequenceTest::SetTaskRunnerForTimer,
- Unretained(this), task_runner2)));
- Wait();
-
- // Task will be scheduled from sequence #1.
- task_runner1->PostTask(
- FROM_HERE,
- BindOnce(&TimerSequenceTest::StartTimer, Unretained(this),
- TimeDelta::FromMilliseconds(1),
- TaskWithSignal(Bind(&TimerSequenceTest::VerifyAffinity,
- Unretained(task_runner2.get())))));
-
- Wait();
-
- // Timer must be destroyed on the sequence it was scheduled from (#1).
- task_runner1->PostTask(
- FROM_HERE,
- TaskWithSignal(Bind(&TimerSequenceTest::DeleteTimer, Unretained(this))));
- Wait();
-}
-
-} // namespace base
diff --git a/base/tools_sanity_unittest.cc b/base/tools_sanity_unittest.cc
deleted file mode 100644
index 761559e..0000000
--- a/base/tools_sanity_unittest.cc
+++ /dev/null
@@ -1,387 +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/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_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 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);
-}
-
-#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/blame_context_unittest.cc b/base/trace_event/blame_context_unittest.cc
deleted file mode 100644
index 12e7857..0000000
--- 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/etw_manifest/BUILD.gn b/base/trace_event/etw_manifest/BUILD.gn
deleted file mode 100644
index 19c4ecf..0000000
--- a/base/trace_event/etw_manifest/BUILD.gn
+++ /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.
-
-import("//build/win/message_compiler.gni")
-
-assert(is_win, "This only runs on Windows.")
-
-message_compiler("chrome_events_win") {
- visibility = [
- "//base/*",
- "//chrome:main_dll",
- ]
-
- sources = [
- "chrome_events_win.man",
- ]
-
- user_mode_logging = true
-
- # The only code generated from chrome_events_win.man is a header file that
- # is included by trace_event_etw_export_win.cc, so there is no need to
- # compile any generated code. The other thing which compile_generated_code
- # controls in this context is linking in the .res file generated from the
- # manifest. However this is only needed for ETW provider registration which
- # is done by UIforETW (https://github.com/google/UIforETW) and therefore the
- # manifest resource can be skipped in Chrome.
- compile_generated_code = false
-}
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 134be0d..0000000
--- 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_tracker_unittest.cc b/base/trace_event/heap_profiler_allocation_context_tracker_unittest.cc
deleted file mode 100644
index c26149e..0000000
--- 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_heap_dump_writer_unittest.cc b/base/trace_event/heap_profiler_heap_dump_writer_unittest.cc
deleted file mode 100644
index 93e8fee..0000000
--- a/base/trace_event/heap_profiler_heap_dump_writer_unittest.cc
+++ /dev/null
@@ -1,330 +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_heap_dump_writer.h"
-
-#include <stddef.h>
-
-#include <memory>
-#include <set>
-#include <string>
-
-#include "base/json/json_reader.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
-#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
-#include "base/trace_event/trace_event_argument.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-using base::trace_event::StackFrame;
-
-// Define all strings once, because the deduplicator requires pointer equality,
-// and string interning is unreliable.
-StackFrame kBrowserMain = StackFrame::FromTraceEventName("BrowserMain");
-StackFrame kRendererMain = StackFrame::FromTraceEventName("RendererMain");
-StackFrame kCreateWidget = StackFrame::FromTraceEventName("CreateWidget");
-StackFrame kInitialize = StackFrame::FromTraceEventName("Initialize");
-StackFrame kGetBitmap = StackFrame::FromTraceEventName("GetBitmap");
-
-const char kInt[] = "int";
-const char kBool[] = "bool";
-const char kString[] = "string";
-
-} // namespace
-
-namespace base {
-namespace trace_event {
-namespace internal {
-
-std::unique_ptr<const Value> WriteAndReadBack(const std::set<Entry>& entries) {
- std::unique_ptr<TracedValue> traced_value = Serialize(entries);
- std::string json;
- traced_value->AppendAsTraceFormat(&json);
- return JSONReader::Read(json);
-}
-
-std::unique_ptr<const DictionaryValue> WriteAndReadBackEntry(Entry entry) {
- std::set<Entry> input_entries;
- input_entries.insert(entry);
-
- std::unique_ptr<const Value> json_dict = WriteAndReadBack(input_entries);
-
- // Note: Ideally these should use |ASSERT_TRUE| instead of |EXPECT_TRUE|, but
- // |ASSERT_TRUE| can only be used in void functions.
- const DictionaryValue* dictionary;
- EXPECT_TRUE(json_dict->GetAsDictionary(&dictionary));
-
- const ListValue* json_entries;
- EXPECT_TRUE(dictionary->GetList("entries", &json_entries));
-
- const DictionaryValue* json_entry;
- EXPECT_TRUE(json_entries->GetDictionary(0, &json_entry));
-
- return json_entry->CreateDeepCopy();
-}
-
-// Given a desired stack frame ID and type ID, looks up the entry in the set and
-// asserts that it is present and has the expected size and count.
-void AssertSizeAndCountEq(const std::set<Entry>& entries,
- int stack_frame_id,
- int type_id,
- const AllocationMetrics& expected) {
- // The comparison operator for |Entry| does not take size into account, so by
- // setting only stack frame ID and type ID, the real entry can be found.
- Entry entry;
- entry.stack_frame_id = stack_frame_id;
- entry.type_id = type_id;
- auto it = entries.find(entry);
-
- ASSERT_NE(entries.end(), it) << "No entry found for sf = " << stack_frame_id
- << ", type = " << type_id << ".";
- ASSERT_EQ(expected.size, it->size) << "Wrong size for sf = " << stack_frame_id
- << ", type = " << type_id << ".";
- ASSERT_EQ(expected.count, it->count)
- << "Wrong count for sf = " << stack_frame_id << ", type = " << type_id
- << ".";
-}
-
-// Given a desired stack frame ID and type ID, asserts that no entry was dumped
-// for that that particular combination of stack frame and type.
-void AssertNotDumped(const std::set<Entry>& entries,
- int stack_frame_id,
- int type_id) {
- // The comparison operator for |Entry| does not take size into account, so by
- // setting only stack frame ID and type ID, the real entry can be found.
- Entry entry;
- entry.stack_frame_id = stack_frame_id;
- entry.type_id = type_id;
- auto it = entries.find(entry);
- ASSERT_EQ(entries.end(), it)
- << "Entry should not be present for sf = " << stack_frame_id
- << ", type = " << type_id << ".";
-}
-
-TEST(HeapDumpWriterTest, BacktraceIndex) {
- Entry entry;
- entry.stack_frame_id = -1; // -1 means empty backtrace.
- entry.type_id = 0;
- entry.size = 1;
- entry.count = 1;
-
- std::unique_ptr<const DictionaryValue> json_entry =
- WriteAndReadBackEntry(entry);
-
- // For an empty backtrace, the "bt" key cannot reference a stack frame.
- // Instead it should be set to the empty string.
- std::string backtrace_index;
- ASSERT_TRUE(json_entry->GetString("bt", &backtrace_index));
- ASSERT_EQ("", backtrace_index);
-
- // Also verify that a non-negative backtrace index is dumped properly.
- entry.stack_frame_id = 2;
- json_entry = WriteAndReadBackEntry(entry);
- ASSERT_TRUE(json_entry->GetString("bt", &backtrace_index));
- ASSERT_EQ("2", backtrace_index);
-}
-
-TEST(HeapDumpWriterTest, TypeId) {
- Entry entry;
- entry.type_id = -1; // -1 means sum over all types.
- entry.stack_frame_id = 0;
- entry.size = 1;
- entry.count = 1;
-
- std::unique_ptr<const DictionaryValue> json_entry =
- WriteAndReadBackEntry(entry);
-
- // Entries for the cumulative size of all types should not have the "type"
- // key set.
- ASSERT_FALSE(json_entry->HasKey("type"));
-
- // Also verify that a non-negative type ID is dumped properly.
- entry.type_id = 2;
- json_entry = WriteAndReadBackEntry(entry);
- std::string type_id;
- ASSERT_TRUE(json_entry->GetString("type", &type_id));
- ASSERT_EQ("2", type_id);
-}
-
-TEST(HeapDumpWriterTest, SizeAndCountAreHexadecimal) {
- // Take a number between 2^63 and 2^64 (or between 2^31 and 2^32 if |size_t|
- // is not 64 bits).
- const size_t large_value =
- sizeof(size_t) == 8 ? 0xffffffffffffffc5 : 0xffffff9d;
- const char* large_value_str =
- sizeof(size_t) == 8 ? "ffffffffffffffc5" : "ffffff9d";
- Entry entry;
- entry.type_id = 0;
- entry.stack_frame_id = 0;
- entry.size = large_value;
- entry.count = large_value;
-
- std::unique_ptr<const DictionaryValue> json_entry =
- WriteAndReadBackEntry(entry);
-
- std::string size;
- ASSERT_TRUE(json_entry->GetString("size", &size));
- ASSERT_EQ(large_value_str, size);
-
- std::string count;
- ASSERT_TRUE(json_entry->GetString("count", &count));
- ASSERT_EQ(large_value_str, count);
-}
-
-TEST(HeapDumpWriterTest, BacktraceTypeNameTable) {
- std::unordered_map<AllocationContext, AllocationMetrics> metrics_by_context;
-
- AllocationContext ctx;
- ctx.backtrace.frames[0] = kBrowserMain;
- ctx.backtrace.frames[1] = kCreateWidget;
- ctx.backtrace.frame_count = 2;
- ctx.type_name = kInt;
-
- // 10 bytes with context { type: int, bt: [BrowserMain, CreateWidget] }.
- metrics_by_context[ctx] = {10, 5};
-
- ctx.type_name = kBool;
-
- // 18 bytes with context { type: bool, bt: [BrowserMain, CreateWidget] }.
- metrics_by_context[ctx] = {18, 18};
-
- ctx.backtrace.frames[0] = kRendererMain;
- ctx.backtrace.frames[1] = kInitialize;
- ctx.backtrace.frame_count = 2;
-
- // 30 bytes with context { type: bool, bt: [RendererMain, Initialize] }.
- metrics_by_context[ctx] = {30, 30};
-
- ctx.type_name = kString;
-
- // 19 bytes with context { type: string, bt: [RendererMain, Initialize] }.
- metrics_by_context[ctx] = {19, 4};
-
- // At this point the heap looks like this:
- //
- // | | CrWidget <- BrMain | Init <- RenMain | Sum |
- // +--------+--------------------+-----------------+-------------+
- // | | size count | size count | size count |
- // | int | 10 5 | 0 0 | 10 5 |
- // | bool | 18 18 | 30 30 | 48 48 |
- // | string | 0 0 | 19 4 | 19 4 |
- // +--------+--------------------+-----------------+-------------+
- // | Sum | 28 23 | 49 34 | 77 57 |
-
- auto stack_frame_deduplicator = WrapUnique(new StackFrameDeduplicator);
- auto type_name_deduplicator = WrapUnique(new TypeNameDeduplicator);
- HeapDumpWriter writer(stack_frame_deduplicator.get(),
- type_name_deduplicator.get(), 10u);
- const std::set<Entry>& dump = writer.Summarize(metrics_by_context);
-
- // Get the indices of the backtraces and types by adding them again to the
- // deduplicator. Because they were added before, the same number is returned.
- StackFrame bt0[] = {kRendererMain, kInitialize};
- StackFrame bt1[] = {kBrowserMain, kCreateWidget};
- int bt_renderer_main = stack_frame_deduplicator->Insert(bt0, bt0 + 1);
- int bt_browser_main = stack_frame_deduplicator->Insert(bt1, bt1 + 1);
- int bt_renderer_main_initialize =
- stack_frame_deduplicator->Insert(bt0, bt0 + 2);
- int bt_browser_main_create_widget =
- stack_frame_deduplicator->Insert(bt1, bt1 + 2);
- int type_id_int = type_name_deduplicator->Insert(kInt);
- int type_id_bool = type_name_deduplicator->Insert(kBool);
- int type_id_string = type_name_deduplicator->Insert(kString);
-
- // Full heap should have size 77.
- AssertSizeAndCountEq(dump, -1, -1, {77, 57});
-
- // 49 bytes in 34 chunks were allocated in RendererMain and children. Also
- // check the type breakdown.
- AssertSizeAndCountEq(dump, bt_renderer_main, -1, {49, 34});
- AssertSizeAndCountEq(dump, bt_renderer_main, type_id_bool, {30, 30});
- AssertSizeAndCountEq(dump, bt_renderer_main, type_id_string, {19, 4});
-
- // 28 bytes in 23 chunks were allocated in BrowserMain and children. Also
- // check the type breakdown.
- AssertSizeAndCountEq(dump, bt_browser_main, -1, {28, 23});
- AssertSizeAndCountEq(dump, bt_browser_main, type_id_int, {10, 5});
- AssertSizeAndCountEq(dump, bt_browser_main, type_id_bool, {18, 18});
-
- // In this test all bytes are allocated in leaf nodes, so check again one
- // level deeper.
- AssertSizeAndCountEq(dump, bt_renderer_main_initialize, -1, {49, 34});
- AssertSizeAndCountEq(dump, bt_renderer_main_initialize, type_id_bool,
- {30, 30});
- AssertSizeAndCountEq(dump, bt_renderer_main_initialize, type_id_string,
- {19, 4});
- AssertSizeAndCountEq(dump, bt_browser_main_create_widget, -1, {28, 23});
- AssertSizeAndCountEq(dump, bt_browser_main_create_widget, type_id_int,
- {10, 5});
- AssertSizeAndCountEq(dump, bt_browser_main_create_widget, type_id_bool,
- {18, 18});
-
- // The type breakdown of the entrie heap should have been dumped as well.
- AssertSizeAndCountEq(dump, -1, type_id_int, {10, 5});
- AssertSizeAndCountEq(dump, -1, type_id_bool, {48, 48});
- AssertSizeAndCountEq(dump, -1, type_id_string, {19, 4});
-}
-
-TEST(HeapDumpWriterTest, InsignificantValuesNotDumped) {
- std::unordered_map<AllocationContext, AllocationMetrics> metrics_by_context;
-
- AllocationContext ctx;
- ctx.backtrace.frames[0] = kBrowserMain;
- ctx.backtrace.frames[1] = kCreateWidget;
- ctx.backtrace.frame_count = 2;
-
- // 0.5 KiB and 1 chunk in BrowserMain -> CreateWidget itself.
- metrics_by_context[ctx] = {512, 1};
-
- // 1 MiB and 1 chunk in BrowserMain -> CreateWidget -> GetBitmap.
- ctx.backtrace.frames[2] = kGetBitmap;
- ctx.backtrace.frame_count = 3;
- metrics_by_context[ctx] = {1024 * 1024, 1};
-
- // 400B and 1 chunk in BrowserMain -> CreateWidget -> Initialize.
- ctx.backtrace.frames[2] = kInitialize;
- ctx.backtrace.frame_count = 3;
- metrics_by_context[ctx] = {400, 1};
-
- auto stack_frame_deduplicator = WrapUnique(new StackFrameDeduplicator);
- auto type_name_deduplicator = WrapUnique(new TypeNameDeduplicator);
- HeapDumpWriter writer(stack_frame_deduplicator.get(),
- type_name_deduplicator.get(), 512u);
- const std::set<Entry>& dump = writer.Summarize(metrics_by_context);
-
- // Get the indices of the backtraces and types by adding them again to the
- // deduplicator. Because they were added before, the same number is returned.
- StackFrame bt0[] = {kBrowserMain, kCreateWidget, kGetBitmap};
- StackFrame bt1[] = {kBrowserMain, kCreateWidget, kInitialize};
- int bt_browser_main = stack_frame_deduplicator->Insert(bt0, bt0 + 1);
- int bt_create_widget = stack_frame_deduplicator->Insert(bt0, bt0 + 2);
- int bt_get_bitmap = stack_frame_deduplicator->Insert(bt0, bt0 + 3);
- int bt_initialize = stack_frame_deduplicator->Insert(bt1, bt1 + 3);
-
- // Full heap should have size of 1 MiB + .9 KiB and 3 chunks.
- AssertSizeAndCountEq(dump, -1, -1 /* No type specified */,
- {1024 * 1024 + 512 + 400, 3});
-
- // |GetBitmap| allocated 1 MiB and 1 chunk.
- AssertSizeAndCountEq(dump, bt_get_bitmap, -1, {1024 * 1024, 1});
-
- // Because |GetBitmap| was dumped, all of its parent nodes should have been
- // dumped too. |CreateWidget| has 1 MiB in |GetBitmap|, 400 bytes in
- // |Initialize|, and 512 bytes of its own and each in 1 chunk.
- AssertSizeAndCountEq(dump, bt_create_widget, -1,
- {1024 * 1024 + 400 + 512, 3});
- AssertSizeAndCountEq(dump, bt_browser_main, -1, {1024 * 1024 + 400 + 512, 3});
-
- // Initialize was not significant, it should not have been dumped.
- AssertNotDumped(dump, bt_initialize, -1);
-}
-
-} // namespace internal
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/heap_profiler_stack_frame_deduplicator_unittest.cc b/base/trace_event/heap_profiler_stack_frame_deduplicator_unittest.cc
deleted file mode 100644
index 194c7aa..0000000
--- a/base/trace_event/heap_profiler_stack_frame_deduplicator_unittest.cc
+++ /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.
-
-#include "base/trace_event/heap_profiler_stack_frame_deduplicator.h"
-
-#include <iterator>
-#include <memory>
-
-#include "base/macros.h"
-#include "base/trace_event/heap_profiler_allocation_context.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-// Define all strings once, because the deduplicator requires pointer equality,
-// and string interning is unreliable.
-StackFrame kBrowserMain = StackFrame::FromTraceEventName("BrowserMain");
-StackFrame kRendererMain = StackFrame::FromTraceEventName("RendererMain");
-StackFrame kCreateWidget = StackFrame::FromTraceEventName("CreateWidget");
-StackFrame kInitialize = StackFrame::FromTraceEventName("Initialize");
-StackFrame kMalloc = StackFrame::FromTraceEventName("malloc");
-
-TEST(StackFrameDeduplicatorTest, SingleBacktrace) {
- StackFrame bt[] = {kBrowserMain, kCreateWidget, kMalloc};
-
- // The call tree should look like this (index in brackets).
- //
- // BrowserMain [0]
- // CreateWidget [1]
- // malloc [2]
-
- std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator);
- ASSERT_EQ(2, dedup->Insert(std::begin(bt), std::end(bt)));
-
- auto iter = dedup->begin();
- ASSERT_EQ(kBrowserMain, (iter + 0)->frame);
- ASSERT_EQ(-1, (iter + 0)->parent_frame_index);
-
- ASSERT_EQ(kCreateWidget, (iter + 1)->frame);
- ASSERT_EQ(0, (iter + 1)->parent_frame_index);
-
- ASSERT_EQ(kMalloc, (iter + 2)->frame);
- ASSERT_EQ(1, (iter + 2)->parent_frame_index);
-
- ASSERT_TRUE(iter + 3 == dedup->end());
-}
-
-TEST(StackFrameDeduplicatorTest, SingleBacktraceWithNull) {
- StackFrame null_frame = StackFrame::FromTraceEventName(nullptr);
- StackFrame bt[] = {kBrowserMain, null_frame, kMalloc};
-
- // Deduplicator doesn't care about what's inside StackFrames,
- // and handles nullptr StackFrame values as any other.
- //
- // So the call tree should look like this (index in brackets).
- //
- // BrowserMain [0]
- // (null) [1]
- // malloc [2]
-
- std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator);
- ASSERT_EQ(2, dedup->Insert(std::begin(bt), std::end(bt)));
-
- auto iter = dedup->begin();
- ASSERT_EQ(kBrowserMain, (iter + 0)->frame);
- ASSERT_EQ(-1, (iter + 0)->parent_frame_index);
-
- ASSERT_EQ(null_frame, (iter + 1)->frame);
- ASSERT_EQ(0, (iter + 1)->parent_frame_index);
-
- ASSERT_EQ(kMalloc, (iter + 2)->frame);
- ASSERT_EQ(1, (iter + 2)->parent_frame_index);
-
- ASSERT_TRUE(iter + 3 == dedup->end());
-}
-
-// Test that there can be different call trees (there can be multiple bottom
-// frames). Also verify that frames with the same name but a different caller
-// are represented as distinct nodes.
-TEST(StackFrameDeduplicatorTest, MultipleRoots) {
- StackFrame bt0[] = {kBrowserMain, kCreateWidget};
- StackFrame bt1[] = {kRendererMain, kCreateWidget};
-
- // The call tree should look like this (index in brackets).
- //
- // BrowserMain [0]
- // CreateWidget [1]
- // RendererMain [2]
- // CreateWidget [3]
- //
- // Note that there will be two instances of CreateWidget,
- // with different parents.
-
- std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator);
- ASSERT_EQ(1, dedup->Insert(std::begin(bt0), std::end(bt0)));
- ASSERT_EQ(3, dedup->Insert(std::begin(bt1), std::end(bt1)));
-
- auto iter = dedup->begin();
- ASSERT_EQ(kBrowserMain, (iter + 0)->frame);
- ASSERT_EQ(-1, (iter + 0)->parent_frame_index);
-
- ASSERT_EQ(kCreateWidget, (iter + 1)->frame);
- ASSERT_EQ(0, (iter + 1)->parent_frame_index);
-
- ASSERT_EQ(kRendererMain, (iter + 2)->frame);
- ASSERT_EQ(-1, (iter + 2)->parent_frame_index);
-
- ASSERT_EQ(kCreateWidget, (iter + 3)->frame);
- ASSERT_EQ(2, (iter + 3)->parent_frame_index);
-
- ASSERT_TRUE(iter + 4 == dedup->end());
-}
-
-TEST(StackFrameDeduplicatorTest, Deduplication) {
- StackFrame bt0[] = {kBrowserMain, kCreateWidget};
- StackFrame bt1[] = {kBrowserMain, kInitialize};
-
- // The call tree should look like this (index in brackets).
- //
- // BrowserMain [0]
- // CreateWidget [1]
- // Initialize [2]
- //
- // Note that BrowserMain will be re-used.
-
- std::unique_ptr<StackFrameDeduplicator> dedup(new StackFrameDeduplicator);
- ASSERT_EQ(1, dedup->Insert(std::begin(bt0), std::end(bt0)));
- ASSERT_EQ(2, dedup->Insert(std::begin(bt1), std::end(bt1)));
-
- auto iter = dedup->begin();
- ASSERT_EQ(kBrowserMain, (iter + 0)->frame);
- ASSERT_EQ(-1, (iter + 0)->parent_frame_index);
-
- ASSERT_EQ(kCreateWidget, (iter + 1)->frame);
- ASSERT_EQ(0, (iter + 1)->parent_frame_index);
-
- ASSERT_EQ(kInitialize, (iter + 2)->frame);
- ASSERT_EQ(0, (iter + 2)->parent_frame_index);
-
- ASSERT_TRUE(iter + 3 == dedup->end());
-
- // Inserting the same backtrace again should return the index of the existing
- // node.
- ASSERT_EQ(1, dedup->Insert(std::begin(bt0), std::end(bt0)));
- ASSERT_EQ(2, dedup->Insert(std::begin(bt1), std::end(bt1)));
- ASSERT_TRUE(dedup->begin() + 3 == dedup->end());
-}
-
-} // namespace trace_event
-} // namespace base
diff --git a/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc b/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc
deleted file mode 100644
index f97808b..0000000
--- a/base/trace_event/heap_profiler_type_name_deduplicator_unittest.cc
+++ /dev/null
@@ -1,83 +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 <memory>
-#include <string>
-
-#include "base/json/json_reader.h"
-#include "base/trace_event/heap_profiler_type_name_deduplicator.h"
-#include "base/values.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-// Define all strings once, because the deduplicator requires pointer equality,
-// and string interning is unreliable.
-const char kInt[] = "int";
-const char kBool[] = "bool";
-const char kString[] = "string";
-const char kNeedsEscape[] = "\"quotes\"";
-
-std::unique_ptr<Value> DumpAndReadBack(
- const TypeNameDeduplicator& deduplicator) {
- std::string json;
- deduplicator.AppendAsTraceFormat(&json);
- return JSONReader::Read(json);
-}
-
-// Inserts a single type name into a new TypeNameDeduplicator instance and
-// checks if the value gets inserted and the exported value for |type_name| is
-// the same as |expected_value|.
-void TestInsertTypeAndReadback(const char* type_name,
- const char* expected_value) {
- std::unique_ptr<TypeNameDeduplicator> dedup(new TypeNameDeduplicator);
- ASSERT_EQ(1, dedup->Insert(type_name));
-
- std::unique_ptr<Value> type_names = DumpAndReadBack(*dedup);
- ASSERT_NE(nullptr, type_names);
-
- const DictionaryValue* dictionary;
- ASSERT_TRUE(type_names->GetAsDictionary(&dictionary));
-
- // When the type name was inserted, it got ID 1. The exported key "1"
- // should be equal to |expected_value|.
- std::string value;
- ASSERT_TRUE(dictionary->GetString("1", &value));
- ASSERT_EQ(expected_value, value);
-}
-
-} // namespace
-
-TEST(TypeNameDeduplicatorTest, Deduplication) {
- // The type IDs should be like this:
- // 0: [unknown]
- // 1: int
- // 2: bool
- // 3: string
-
- std::unique_ptr<TypeNameDeduplicator> dedup(new TypeNameDeduplicator);
- ASSERT_EQ(1, dedup->Insert(kInt));
- ASSERT_EQ(2, dedup->Insert(kBool));
- ASSERT_EQ(3, dedup->Insert(kString));
-
- // Inserting again should return the same IDs.
- ASSERT_EQ(2, dedup->Insert(kBool));
- ASSERT_EQ(1, dedup->Insert(kInt));
- ASSERT_EQ(3, dedup->Insert(kString));
-
- // A null pointer should yield type ID 0.
- ASSERT_EQ(0, dedup->Insert(nullptr));
-}
-
-TEST(TypeNameDeduplicatorTest, EscapeTypeName) {
- // Reading json should not fail, because the type name should have been
- // escaped properly and exported value should contain quotes.
- TestInsertTypeAndReadback(kNeedsEscape, kNeedsEscape);
-}
-
-} // namespace trace_event
-} // namespace base
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 9b9eb17..0000000
--- a/base/trace_event/java_heap_dump_provider_android_unittest.cc
+++ /dev/null
@@ -1,23 +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(nullptr, dump_args));
-
- jhdp->OnMemoryDump(dump_args, pmd.get());
-}
-
-} // namespace trace_event
-} // namespace base
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 3818629..0000000
--- a/base/trace_event/memory_allocator_dump_unittest.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/memory_allocator_dump.h"
-
-#include <stdint.h>
-
-#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
-#include "base/trace_event/heap_profiler_serialization_state.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_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(new HeapProfilerSerializationState, 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());
- pmd.SerializeHeapProfilerDumpsInto(traced_value.get());
-}
-
-TEST(MemoryAllocatorDumpTest, GetSize) {
- MemoryDumpArgs dump_args = {MemoryDumpLevelOfDetail::DETAILED};
- ProcessMemoryDump pmd(new HeapProfilerSerializationState, 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(new HeapProfilerSerializationState, 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(new HeapProfilerSerializationState, 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(new HeapProfilerSerializationState, 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_unittest.cc b/base/trace_event/memory_dump_manager_unittest.cc
deleted file mode 100644
index 8ed5fb3..0000000
--- a/base/trace_event/memory_dump_manager_unittest.cc
+++ /dev/null
@@ -1,884 +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/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_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));
- MOCK_METHOD1(OnHeapProfilingEnabled, void(bool enabled));
- MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t* memory_total));
- MOCK_METHOD0(SuspendFastMemoryPolling, void());
-
- MockMemoryDumpProvider() : enable_mock_destructor(false) {
- ON_CALL(*this, OnMemoryDump(_, _))
- .WillByDefault(
- Invoke([](const MemoryDumpArgs&, ProcessMemoryDump* pmd) -> bool {
- return true;
- }));
-
- ON_CALL(*this, PollFastMemoryTotal(_))
- .WillByDefault(
- Invoke([](uint64_t* memory_total) -> void { NOTREACHED(); }));
- }
- ~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 HeapProfilerSerializationState object is actually
-// shared over time.
-TEST_F(MemoryDumpManagerTest, HeapProfilerSerializationState) {
- MockMemoryDumpProvider mdp1;
- MockMemoryDumpProvider mdp2;
- RegisterDumpProvider(&mdp1, nullptr);
- RegisterDumpProvider(&mdp2, nullptr);
-
- EnableForTracing();
- const HeapProfilerSerializationState* heap_profiler_serialization_state =
- mdm_->heap_profiler_serialization_state_for_testing().get();
- EXPECT_CALL(mdp1, OnMemoryDump(_, _))
- .Times(2)
- .WillRepeatedly(
- Invoke([heap_profiler_serialization_state](
- const MemoryDumpArgs&, ProcessMemoryDump* pmd) -> bool {
- EXPECT_EQ(heap_profiler_serialization_state,
- pmd->heap_profiler_serialization_state().get());
- return true;
- }));
- EXPECT_CALL(mdp2, OnMemoryDump(_, _))
- .Times(2)
- .WillRepeatedly(
- Invoke([heap_profiler_serialization_state](
- const MemoryDumpArgs&, ProcessMemoryDump* pmd) -> bool {
- EXPECT_EQ(heap_profiler_serialization_state,
- pmd->heap_profiler_serialization_state().get());
- return true;
- }));
-
- for (int i = 0; i < 2; ++i) {
- EXPECT_TRUE(RequestProcessDumpAndWait(MemoryDumpType::EXPLICITLY_TRIGGERED,
- MemoryDumpLevelOfDetail::DETAILED));
- }
-
- DisableTracing();
-}
-
-// 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_scheduler_unittest.cc b/base/trace_event/memory_dump_scheduler_unittest.cc
deleted file mode 100644
index d5993b6..0000000
--- 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_peak_detector_unittest.cc b/base/trace_event/memory_peak_detector_unittest.cc
deleted file mode 100644
index bc10c80..0000000
--- a/base/trace_event/memory_peak_detector_unittest.cc
+++ /dev/null
@@ -1,564 +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_peak_detector.h"
-
-#include <memory>
-
-#include "base/bind.h"
-#include "base/logging.h"
-#include "base/run_loop.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "base/trace_event/memory_dump_provider.h"
-#include "base/trace_event/memory_dump_provider_info.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using ::testing::_;
-using ::testing::Invoke;
-using ::testing::Return;
-
-namespace base {
-namespace trace_event {
-
-namespace {
-
-const TimeDelta kMs = TimeDelta::FromMilliseconds(1);
-const MemoryPeakDetector::Config kConfigNoCallbacks(
- 1 /* polling_interval_ms */,
- 60000 /* min_time_between_peaks_ms */,
- false /* enable_verbose_poll_tracing */
- );
-
-class MockMemoryDumpProvider : public MemoryDumpProvider {
- public:
- bool OnMemoryDump(const MemoryDumpArgs&, ProcessMemoryDump*) override {
- NOTREACHED();
- return true;
- }
-
- MOCK_METHOD1(PollFastMemoryTotal, void(uint64_t*));
-};
-
-// Wrapper to use gmock on a callback.
-struct OnPeakDetectedWrapper {
- MOCK_METHOD0(OnPeak, void());
-};
-
-} // namespace
-
-class MemoryPeakDetectorTest : public testing::Test {
- public:
- struct FriendDeleter {
- void operator()(MemoryPeakDetector* inst) { delete inst; }
- };
-
- MemoryPeakDetectorTest() : testing::Test() {}
- static const uint64_t kSlidingWindowNumSamples =
- MemoryPeakDetector::kSlidingWindowNumSamples;
-
- std::unique_ptr<MemoryPeakDetector, FriendDeleter> NewInstance() {
- return std::unique_ptr<MemoryPeakDetector, FriendDeleter>(
- new MemoryPeakDetector());
- }
-
- void RestartThreadAndReinitializePeakDetector() {
- bg_thread_.reset(new Thread("Peak Detector Test Thread"));
- bg_thread_->Start();
- peak_detector_ = NewInstance();
- peak_detector_->Setup(
- Bind(&MemoryPeakDetectorTest::MockGetDumpProviders, Unretained(this)),
- bg_thread_->task_runner(),
- Bind(&OnPeakDetectedWrapper::OnPeak, Unretained(&on_peak_callback_)));
- }
-
- void SetUp() override {
- get_mdp_call_count_ = 0;
- RestartThreadAndReinitializePeakDetector();
- }
-
- void TearDown() override {
- peak_detector_->TearDown();
- bg_thread_->FlushForTesting();
- EXPECT_EQ(MemoryPeakDetector::NOT_INITIALIZED, GetPeakDetectorState());
- bg_thread_.reset();
- dump_providers_.clear();
- }
-
- // Calls MemoryPeakDetector::state_for_testing() on the bg thread and returns
- // the result on the current thread.
- MemoryPeakDetector::State GetPeakDetectorState() {
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- MemoryPeakDetector::State res = MemoryPeakDetector::NOT_INITIALIZED;
- auto get_fn = [](MemoryPeakDetector* peak_detector, WaitableEvent* evt,
- MemoryPeakDetector::State* res) {
- *res = peak_detector->state_for_testing();
- evt->Signal();
- };
- bg_thread_->task_runner()->PostTask(
- FROM_HERE, BindOnce(get_fn, Unretained(&*peak_detector_),
- Unretained(&evt), Unretained(&res)));
- evt.Wait();
- return res;
- }
-
- // Calls MemoryPeakDetector::poll_tasks_count_for_testing() on the bg thread
- // and returns the result on the current thread.
- uint32_t GetNumPollingTasksRan() {
- uint32_t res = 0;
- auto get_fn = [](MemoryPeakDetector* peak_detector, WaitableEvent* evt,
- uint32_t* res) {
- *res = peak_detector->poll_tasks_count_for_testing();
- evt->Signal();
- };
-
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- bg_thread_->task_runner()->PostTask(
- FROM_HERE, BindOnce(get_fn, Unretained(&*peak_detector_),
- Unretained(&evt), Unretained(&res)));
- evt.Wait();
- return res;
- }
-
- // Runs the peak detector with a mock MDP with the given
- // |config|. The mock MDP will invoke the |poll_function| on any call to
- // PollFastMemoryTotal(), until |num_samples| have been polled.
- // It returns the number of peaks detected.
- uint32_t RunWithCustomPollFunction(
- MemoryPeakDetector::Config config,
- uint32_t num_samples,
- RepeatingCallback<uint64_t(uint32_t)> poll_function) {
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
- dump_providers_.push_back(mdp);
- uint32_t cur_sample_idx = 0;
- EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke(
- [&cur_sample_idx, &evt, poll_function, num_samples](uint64_t* mem) {
- if (cur_sample_idx >= num_samples) {
- *mem = 1;
- evt.Signal();
- } else {
- *mem = poll_function.Run(cur_sample_idx++);
- }
- }));
-
- uint32_t num_peaks = 0;
- EXPECT_CALL(on_peak_callback_, OnPeak())
- .WillRepeatedly(Invoke([&num_peaks] { num_peaks++; }));
- peak_detector_->Start(config);
- evt.Wait(); // Wait for |num_samples| invocations of PollFastMemoryTotal().
- peak_detector_->Stop();
- EXPECT_EQ(num_samples, cur_sample_idx);
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- return num_peaks;
- }
-
- // Called on the |bg_thread_|.
- void MockGetDumpProviders(MemoryPeakDetector::DumpProvidersList* mdps) {
- get_mdp_call_count_++;
- *mdps = dump_providers_;
- }
-
- uint32_t GetNumGetDumpProvidersCalls() {
- bg_thread_->FlushForTesting();
- return get_mdp_call_count_;
- }
-
- scoped_refptr<MemoryDumpProviderInfo> CreateMockDumpProvider() {
- std::unique_ptr<MockMemoryDumpProvider> mdp(new MockMemoryDumpProvider());
- MemoryDumpProvider::Options opt;
- opt.is_fast_polling_supported = true;
- scoped_refptr<MemoryDumpProviderInfo> mdp_info(new MemoryDumpProviderInfo(
- mdp.get(), "Mock MDP", nullptr, opt,
- false /* whitelisted_for_background_mode */));
-
- // The |mdp| instance will be destroyed together with the |mdp_info|.
- mdp_info->owned_dump_provider = std::move(mdp);
- return mdp_info;
- }
-
- static MockMemoryDumpProvider& GetMockMDP(
- const scoped_refptr<MemoryDumpProviderInfo>& mdp_info) {
- return *static_cast<MockMemoryDumpProvider*>(mdp_info->dump_provider);
- }
-
- static uint64_t PollFunctionThatCausesPeakViaStdDev(uint32_t sample_idx) {
- // Start with a baseline of 50 MB.
- if (sample_idx < kSlidingWindowNumSamples)
- return 50000 + (sample_idx % 3) * 100;
-
- // Then 10 samples around 80 MB
- if (sample_idx < 10 + kSlidingWindowNumSamples)
- return 80000 + (sample_idx % 3) * 200;
-
- // Than back to 60 MB.
- if (sample_idx < 2 * kSlidingWindowNumSamples)
- return 60000 + (sample_idx % 3) * 100;
-
- // Then 20 samples around 120 MB.
- if (sample_idx < 20 + 2 * kSlidingWindowNumSamples)
- return 120000 + (sample_idx % 3) * 200;
-
- // Then back to idle to around 50 MB until the end.
- return 50000 + (sample_idx % 3) * 100;
- }
-
- protected:
- MemoryPeakDetector::DumpProvidersList dump_providers_;
- uint32_t get_mdp_call_count_;
- std::unique_ptr<MemoryPeakDetector, FriendDeleter> peak_detector_;
- std::unique_ptr<Thread> bg_thread_;
- OnPeakDetectedWrapper on_peak_callback_;
-};
-
-const uint64_t MemoryPeakDetectorTest::kSlidingWindowNumSamples;
-
-TEST_F(MemoryPeakDetectorTest, GetDumpProvidersFunctionCalled) {
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
- EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
-
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- EXPECT_EQ(0u, GetNumPollingTasksRan());
-}
-
-TEST_F(MemoryPeakDetectorTest, ThrottleAndNotifyBeforeInitialize) {
- peak_detector_->TearDown();
-
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
- EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
- dump_providers_.push_back(mdp);
- peak_detector_->Throttle();
- peak_detector_->NotifyMemoryDumpProvidersChanged();
- EXPECT_EQ(MemoryPeakDetector::NOT_INITIALIZED, GetPeakDetectorState());
- RestartThreadAndReinitializePeakDetector();
-
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
- evt.Wait(); // Wait for a PollFastMemoryTotal() call.
-
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
- EXPECT_GE(GetNumPollingTasksRan(), 1u);
-}
-
-TEST_F(MemoryPeakDetectorTest, DoubleStop) {
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
-
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
-
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
-
- EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
- EXPECT_EQ(0u, GetNumPollingTasksRan());
-}
-
-TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredBeforeStart) {
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
- EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
- dump_providers_.push_back(mdp);
-
- peak_detector_->Start(kConfigNoCallbacks);
- evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP.
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
-
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
- EXPECT_GT(GetNumPollingTasksRan(), 0u);
-}
-
-TEST_F(MemoryPeakDetectorTest, ReInitializeAndRebindToNewThread) {
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
- EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
- dump_providers_.push_back(mdp);
-
- for (int i = 0; i < 5; ++i) {
- evt.Reset();
- peak_detector_->Start(kConfigNoCallbacks);
- evt.Wait(); // Wait for a PollFastMemoryTotal() call.
- // Check that calling TearDown implicitly does a Stop().
- peak_detector_->TearDown();
-
- // Reinitialize and re-bind to a new task runner.
- RestartThreadAndReinitializePeakDetector();
- }
-}
-
-TEST_F(MemoryPeakDetectorTest, OneDumpProviderRegisteredOutOfBand) {
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
- EXPECT_EQ(1u, GetNumGetDumpProvidersCalls());
-
- // Check that no poll tasks are posted before any dump provider is registered.
- PlatformThread::Sleep(5 * kConfigNoCallbacks.polling_interval_ms * kMs);
- EXPECT_EQ(0u, GetNumPollingTasksRan());
-
- // Registed the MDP After Start() has been issued and expect that the
- // PeakDetector transitions ENABLED -> RUNNING on the next
- // NotifyMemoryDumpProvidersChanged() call.
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
- EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&evt](uint64_t*) { evt.Signal(); }));
- dump_providers_.push_back(mdp);
- peak_detector_->NotifyMemoryDumpProvidersChanged();
-
- evt.Wait(); // Signaled when PollFastMemoryTotal() is called on the MockMDP.
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
- EXPECT_EQ(2u, GetNumGetDumpProvidersCalls());
-
- // Now simulate the unregisration and expect that the PeakDetector transitions
- // back to ENABLED.
- dump_providers_.clear();
- peak_detector_->NotifyMemoryDumpProvidersChanged();
- EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
- EXPECT_EQ(3u, GetNumGetDumpProvidersCalls());
- uint32_t num_poll_tasks = GetNumPollingTasksRan();
- EXPECT_GT(num_poll_tasks, 0u);
-
- // At this point, no more polling tasks should be posted.
- PlatformThread::Sleep(5 * kConfigNoCallbacks.polling_interval_ms * kMs);
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan());
-}
-
-// Test that a sequence of Start()/Stop() back-to-back doesn't end up creating
-// several outstanding timer tasks and instead respects the polling_interval_ms.
-TEST_F(MemoryPeakDetectorTest, StartStopQuickly) {
- WaitableEvent evt(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp = CreateMockDumpProvider();
- dump_providers_.push_back(mdp);
- const uint32_t kNumPolls = 20;
- uint32_t polls_done = 0;
- EXPECT_CALL(GetMockMDP(mdp), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&polls_done, &evt, kNumPolls](uint64_t*) {
- if (++polls_done == kNumPolls)
- evt.Signal();
- }));
-
- const TimeTicks tstart = TimeTicks::Now();
- for (int i = 0; i < 5; i++) {
- peak_detector_->Start(kConfigNoCallbacks);
- peak_detector_->Stop();
- }
-
- bg_thread_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce([](uint32_t* polls_done) { *polls_done = 0; },
- &polls_done));
-
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
- evt.Wait(); // Wait for kNumPolls.
- const double time_ms = (TimeTicks::Now() - tstart).InMillisecondsF();
-
- EXPECT_GE(time_ms, (kNumPolls - 1) * kConfigNoCallbacks.polling_interval_ms);
- peak_detector_->Stop();
-}
-
-TEST_F(MemoryPeakDetectorTest, RegisterAndUnregisterTwoDumpProviders) {
- WaitableEvent evt1(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- WaitableEvent evt2(WaitableEvent::ResetPolicy::MANUAL,
- WaitableEvent::InitialState::NOT_SIGNALED);
- scoped_refptr<MemoryDumpProviderInfo> mdp1 = CreateMockDumpProvider();
- scoped_refptr<MemoryDumpProviderInfo> mdp2 = CreateMockDumpProvider();
- EXPECT_CALL(GetMockMDP(mdp1), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&evt1](uint64_t*) { evt1.Signal(); }));
- EXPECT_CALL(GetMockMDP(mdp2), PollFastMemoryTotal(_))
- .WillRepeatedly(Invoke([&evt2](uint64_t*) { evt2.Signal(); }));
-
- // Register only one MDP and start the detector.
- dump_providers_.push_back(mdp1);
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
-
- // Wait for one poll task and then register also the other one.
- evt1.Wait();
- dump_providers_.push_back(mdp2);
- peak_detector_->NotifyMemoryDumpProvidersChanged();
- evt2.Wait();
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
-
- // Now unregister the first MDP and check that everything is still running.
- dump_providers_.erase(dump_providers_.begin());
- peak_detector_->NotifyMemoryDumpProvidersChanged();
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
-
- // Now unregister both and check that the detector goes to idle.
- dump_providers_.clear();
- peak_detector_->NotifyMemoryDumpProvidersChanged();
- EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
-
- // Now re-register both and check that the detector re-activates posting
- // new polling tasks.
- uint32_t num_poll_tasks = GetNumPollingTasksRan();
- evt1.Reset();
- evt2.Reset();
- dump_providers_.push_back(mdp1);
- dump_providers_.push_back(mdp2);
- peak_detector_->NotifyMemoryDumpProvidersChanged();
- evt1.Wait();
- evt2.Wait();
- EXPECT_EQ(MemoryPeakDetector::RUNNING, GetPeakDetectorState());
- EXPECT_GT(GetNumPollingTasksRan(), num_poll_tasks);
-
- // Stop everything, tear down the MDPs, restart the detector and check that
- // it detector doesn't accidentally try to re-access them.
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- dump_providers_.clear();
- mdp1 = nullptr;
- mdp2 = nullptr;
-
- num_poll_tasks = GetNumPollingTasksRan();
- peak_detector_->Start(kConfigNoCallbacks);
- EXPECT_EQ(MemoryPeakDetector::ENABLED, GetPeakDetectorState());
- PlatformThread::Sleep(5 * kConfigNoCallbacks.polling_interval_ms * kMs);
-
- peak_detector_->Stop();
- EXPECT_EQ(MemoryPeakDetector::DISABLED, GetPeakDetectorState());
- EXPECT_EQ(num_poll_tasks, GetNumPollingTasksRan());
-
- EXPECT_EQ(6u, GetNumGetDumpProvidersCalls());
-}
-
-// Tests the behavior of the static threshold detector, which is supposed to
-// detect a peak whenever an increase >= threshold is detected.
-TEST_F(MemoryPeakDetectorTest, StaticThreshold) {
- const uint32_t kNumSamples = 2 * kSlidingWindowNumSamples;
- constexpr uint32_t kNumSamplesPerStep = 10;
- constexpr uint64_t kThreshold = 1000000;
- peak_detector_->SetStaticThresholdForTesting(kThreshold);
- const MemoryPeakDetector::Config kConfig(
- 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
- false /* enable_verbose_poll_tracing */
- );
-
- // The mocked PollFastMemoryTotal() will return a step function,
- // e.g. (1, 1, 1, 5, 5, 5, ...) where the steps are 2x threshold, in order to
- // trigger only the static threshold logic.
- auto poll_fn = Bind(
- [](const uint32_t kNumSamplesPerStep, const uint64_t kThreshold,
- uint32_t sample_idx) -> uint64_t {
- return (1 + sample_idx / kNumSamplesPerStep) * 2 * kThreshold;
- },
- kNumSamplesPerStep, kThreshold);
- uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
- EXPECT_EQ(kNumSamples / kNumSamplesPerStep - 1, num_peaks);
-}
-
-// Checks the throttling logic of Config's |min_time_between_peaks_ms|.
-TEST_F(MemoryPeakDetectorTest, PeakCallbackThrottling) {
- const size_t kNumSamples = 2 * kSlidingWindowNumSamples;
- constexpr uint64_t kThreshold = 1000000;
- peak_detector_->SetStaticThresholdForTesting(kThreshold);
- const MemoryPeakDetector::Config kConfig(
- 1 /* polling_interval_ms */, 4 /* min_time_between_peaks_ms */,
- false /* enable_verbose_poll_tracing */
- );
-
- // Each mock value returned is N * 2 * threshold, so all of them would be
- // eligible to be a peak if throttling wasn't enabled.
- auto poll_fn = Bind(
- [](uint64_t kThreshold, uint32_t sample_idx) -> uint64_t {
- return (sample_idx + 1) * 2 * kThreshold;
- },
- kThreshold);
- uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
- const uint32_t kExpectedThrottlingRate =
- kConfig.min_time_between_peaks_ms / kConfig.polling_interval_ms;
- EXPECT_LT(num_peaks, kNumSamples / kExpectedThrottlingRate);
-}
-
-TEST_F(MemoryPeakDetectorTest, StdDev) {
- // Set the threshold to some arbitrarily high value, so that the static
- // threshold logic is not hit in this test.
- constexpr uint64_t kThreshold = 1024 * 1024 * 1024;
- peak_detector_->SetStaticThresholdForTesting(kThreshold);
- const size_t kNumSamples = 3 * kSlidingWindowNumSamples;
- const MemoryPeakDetector::Config kConfig(
- 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
- false /* enable_verbose_poll_tracing */
- );
-
- auto poll_fn = Bind(&PollFunctionThatCausesPeakViaStdDev);
- uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
- EXPECT_EQ(2u, num_peaks); // 80 MB, 120 MB.
-}
-
-// Tests that Throttle() actually holds back peak notifications.
-TEST_F(MemoryPeakDetectorTest, Throttle) {
- constexpr uint64_t kThreshold = 1024 * 1024 * 1024;
- const uint32_t kNumSamples = 3 * kSlidingWindowNumSamples;
- peak_detector_->SetStaticThresholdForTesting(kThreshold);
- const MemoryPeakDetector::Config kConfig(
- 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
- false /* enable_verbose_poll_tracing */
- );
-
- auto poll_fn = Bind(
- [](MemoryPeakDetector* peak_detector, uint32_t sample_idx) -> uint64_t {
- if (sample_idx % 20 == 20 - 1)
- peak_detector->Throttle();
- return PollFunctionThatCausesPeakViaStdDev(sample_idx);
- },
- Unretained(&*peak_detector_));
- uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
- EXPECT_EQ(0u, num_peaks);
-}
-
-// Tests that the windows stddev state is not carried over through
-// Stop() -> Start() sequences.
-TEST_F(MemoryPeakDetectorTest, RestartClearsState) {
- constexpr uint64_t kThreshold = 1024 * 1024 * 1024;
- peak_detector_->SetStaticThresholdForTesting(kThreshold);
- const size_t kNumSamples = 3 * kSlidingWindowNumSamples;
- const MemoryPeakDetector::Config kConfig(
- 1 /* polling_interval_ms */, 0 /* min_time_between_peaks_ms */,
- false /* enable_verbose_poll_tracing */
- );
- auto poll_fn = Bind(
- [](MemoryPeakDetector* peak_detector,
- const uint32_t kSlidingWindowNumSamples,
- MemoryPeakDetector::Config kConfig, uint32_t sample_idx) -> uint64_t {
- if (sample_idx % kSlidingWindowNumSamples ==
- kSlidingWindowNumSamples - 1) {
- peak_detector->Stop();
- peak_detector->Start(kConfig);
- }
- return PollFunctionThatCausesPeakViaStdDev(sample_idx);
- },
- Unretained(&*peak_detector_), kSlidingWindowNumSamples, kConfig);
- uint32_t num_peaks = RunWithCustomPollFunction(kConfig, kNumSamples, poll_fn);
- EXPECT_EQ(0u, num_peaks);
-}
-
-} // namespace trace_event
-} // namespace base
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 7f8efc7..0000000
--- 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_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_unittest.cc b/base/trace_event/process_memory_dump_unittest.cc
deleted file mode 100644
index b33a39e..0000000
--- a/base/trace_event/process_memory_dump_unittest.cc
+++ /dev/null
@@ -1,584 +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_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};
-
-TracedValue* GetHeapDump(const ProcessMemoryDump& pmd, const char* name) {
- auto it = pmd.heap_dumps().find(name);
- return it == pmd.heap_dumps().end() ? nullptr : it->second.get();
-}
-
-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) {
- auto heap_state = MakeRefCounted<HeapProfilerSerializationState>();
- heap_state->SetStackFrameDeduplicator(
- std::make_unique<StackFrameDeduplicator>());
- heap_state->SetTypeNameDeduplicator(std::make_unique<TypeNameDeduplicator>());
-
- ProcessMemoryDump pmd1 = ProcessMemoryDump(heap_state, 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());
- EXPECT_EQ(heap_state.get(), pmd2.heap_profiler_serialization_state().get());
-
- // Check that calling serialization routines doesn't cause a crash.
- auto traced_value = std::make_unique<TracedValue>();
- pmd2.SerializeAllocatorDumpsInto(traced_value.get());
- pmd2.SerializeHeapProfilerDumpsInto(traced_value.get());
-}
-
-TEST(ProcessMemoryDumpTest, MoveAssignment) {
- auto heap_state = MakeRefCounted<HeapProfilerSerializationState>();
- heap_state->SetStackFrameDeduplicator(
- std::make_unique<StackFrameDeduplicator>());
- heap_state->SetTypeNameDeduplicator(std::make_unique<TypeNameDeduplicator>());
-
- ProcessMemoryDump pmd1 = ProcessMemoryDump(heap_state, kDetailedDumpArgs);
- pmd1.CreateAllocatorDump("mad1");
- pmd1.CreateAllocatorDump("mad2");
- pmd1.AddOwnershipEdge(MemoryAllocatorDumpGuid(42),
- MemoryAllocatorDumpGuid(4242));
-
- ProcessMemoryDump pmd2(nullptr, {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());
- EXPECT_EQ(heap_state.get(), pmd2.heap_profiler_serialization_state().get());
-
- // Check that calling serialization routines doesn't cause a crash.
- auto traced_value = std::make_unique<TracedValue>();
- pmd2.SerializeAllocatorDumpsInto(traced_value.get());
- pmd2.SerializeHeapProfilerDumpsInto(traced_value.get());
-}
-
-TEST(ProcessMemoryDumpTest, Clear) {
- std::unique_ptr<ProcessMemoryDump> pmd1(
- new ProcessMemoryDump(nullptr, 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());
- pmd1->SerializeHeapProfilerDumpsInto(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->SerializeHeapProfilerDumpsInto(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;
-
- scoped_refptr<HeapProfilerSerializationState>
- heap_profiler_serialization_state = new HeapProfilerSerializationState;
- heap_profiler_serialization_state->SetStackFrameDeduplicator(
- WrapUnique(new StackFrameDeduplicator));
- heap_profiler_serialization_state->SetTypeNameDeduplicator(
- WrapUnique(new TypeNameDeduplicator));
- std::unique_ptr<ProcessMemoryDump> pmd1(new ProcessMemoryDump(
- heap_profiler_serialization_state.get(), 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(
- heap_profiler_serialization_state.get(), 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());
- ASSERT_TRUE(pmd2->heap_dumps().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());
- pmd2->SerializeHeapProfilerDumpsInto(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());
- ASSERT_EQ(4u, pmd1->heap_dumps().size());
- ASSERT_TRUE(GetHeapDump(*pmd1, "pmd1/heap_dump1") != nullptr);
- ASSERT_TRUE(GetHeapDump(*pmd1, "pmd1/heap_dump2") != nullptr);
- ASSERT_TRUE(GetHeapDump(*pmd1, "pmd2/heap_dump1") != nullptr);
- ASSERT_TRUE(GetHeapDump(*pmd1, "pmd2/heap_dump2") != nullptr);
-
- // Check that calling serialization routines doesn't cause a crash.
- traced_value.reset(new TracedValue);
- pmd1->SerializeAllocatorDumpsInto(traced_value.get());
- pmd1->SerializeHeapProfilerDumpsInto(traced_value.get());
-
- pmd1.reset();
-}
-
-TEST(ProcessMemoryDumpTest, OverrideOwnershipEdge) {
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(nullptr, 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(nullptr, 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->SerializeHeapProfilerDumpsInto(traced_value.get());
-
- pmd.reset();
-}
-
-TEST(ProcessMemoryDumpTest, GlobalAllocatorDumpTest) {
- std::unique_ptr<ProcessMemoryDump> pmd(
- new ProcessMemoryDump(nullptr, 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(nullptr, 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(nullptr, background_args));
- ProcessMemoryDump::is_black_hole_non_fatal_for_testing_ = true;
- SetAllocatorDumpNameWhitelistForTesting(kTestDumpNameWhitelist);
- MemoryAllocatorDump* black_hole_mad = pmd->GetBlackHoleMad();
-
- // 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(black_hole_mad, 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(nullptr, dump_args);
- pmd1.set_process_token_for_testing(process_token_one);
- MemoryAllocatorDump* mad1 = pmd1.CreateAllocatorDump("foo");
-
- ProcessMemoryDump pmd2(nullptr, 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(nullptr, dump_args);
- MemoryAllocatorDump* mad3 = pmd3.CreateAllocatorDump("foo");
-
- // PMD's for different processes produce different GUIDs even for the same
- // names:
- ProcessMemoryDump pmd4(nullptr, 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)
-TEST(ProcessMemoryDumpTest, 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);
-}
-
-TEST(ProcessMemoryDumpTest, 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_category_unittest.cc b/base/trace_event/trace_category_unittest.cc
deleted file mode 100644
index 964064e..0000000
--- a/base/trace_event/trace_category_unittest.cc
+++ /dev/null
@@ -1,148 +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 "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.
-TEST_F(TraceCategoryTest, 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_unittest.cc b/base/trace_event/trace_config_unittest.cc
deleted file mode 100644
index 3cb6d61..0000000
--- a/base/trace_event/trace_config_unittest.cc
+++ /dev/null
@@ -1,673 +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\":\"peak_memory_usage\""
- "}"
- "]"
- "},"
- "\"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);
-
- std::string tc_str4 =
- TraceConfigMemoryTestUtil::GetTraceConfig_PeakDetectionTrigger(
- 1 /*heavy_period */);
- TraceConfig tc4(tc_str4);
- EXPECT_EQ(tc_str4, tc4.ToString());
- ASSERT_EQ(1u, tc4.memory_dump_config().triggers.size());
- EXPECT_EQ(1u, tc4.memory_dump_config().triggers[0].min_time_between_dumps_ms);
- EXPECT_EQ(MemoryDumpLevelOfDetail::DETAILED,
- tc4.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_android_unittest.cc b/base/trace_event/trace_event_android_unittest.cc
deleted file mode 100644
index 58bd77e..0000000
--- 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_unittest.cc b/base/trace_event/trace_event_argument_unittest.cc
deleted file mode 100644
index 448b2d5..0000000
--- 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_system_stats_monitor_unittest.cc b/base/trace_event/trace_event_system_stats_monitor_unittest.cc
deleted file mode 100644
index 978746d..0000000
--- 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_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 a413ee5..0000000
--- 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", ×tamp));
- 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/tuple_unittest.cc b/base/tuple_unittest.cc
deleted file mode 100644
index 4b38797..0000000
--- a/base/tuple_unittest.cc
+++ /dev/null
@@ -1,118 +0,0 @@
-// Copyright (c) 2006-2008 The Chromium Authors. 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/tuple.h"
-
-#include "base/compiler_specific.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-void DoAdd(int a, int b, int c, int* res) {
- *res = a + b + c;
-}
-
-struct Addy {
- Addy() = default;
- void DoAdd(int a, int b, int c, int d, int* res) {
- *res = a + b + c + d;
- }
-};
-
-struct Addz {
- Addz() = default;
- void DoAdd(int a, int b, int c, int d, int e, int* res) {
- *res = a + b + c + d + e;
- }
-};
-
-} // namespace
-
-TEST(TupleTest, Basic) {
- std::tuple<> t0 = std::make_tuple();
- ALLOW_UNUSED_LOCAL(t0);
- std::tuple<int> t1(1);
- std::tuple<int, const char*> t2 =
- std::make_tuple(1, static_cast<const char*>("wee"));
- ALLOW_UNUSED_LOCAL(t2);
- std::tuple<int, int, int> t3(1, 2, 3);
- ALLOW_UNUSED_LOCAL(t3);
- std::tuple<int, int, int, int*> t4(1, 2, 3, &std::get<0>(t1));
- std::tuple<int, int, int, int, int*> t5(1, 2, 3, 4, &std::get<0>(t4));
- std::tuple<int, int, int, int, int, int*> t6(1, 2, 3, 4, 5, &std::get<0>(t4));
-
- EXPECT_EQ(1, std::get<0>(t1));
- DispatchToFunction(&DoAdd, t4);
- EXPECT_EQ(6, std::get<0>(t1));
-
- int res = 0;
- DispatchToFunction(&DoAdd, std::make_tuple(9, 8, 7, &res));
- EXPECT_EQ(24, res);
-
- Addy addy;
- EXPECT_EQ(1, std::get<0>(t4));
- DispatchToMethod(&addy, &Addy::DoAdd, t5);
- EXPECT_EQ(10, std::get<0>(t4));
-
- Addz addz;
- EXPECT_EQ(10, std::get<0>(t4));
- DispatchToMethod(&addz, &Addz::DoAdd, t6);
- EXPECT_EQ(15, std::get<0>(t4));
-}
-
-namespace {
-
-struct CopyLogger {
- CopyLogger() { ++TimesConstructed; }
- CopyLogger(const CopyLogger& tocopy) { ++TimesConstructed; ++TimesCopied; }
- ~CopyLogger() = default;
-
- static int TimesCopied;
- static int TimesConstructed;
-};
-
-void SomeLoggerMethRef(const CopyLogger& logy, const CopyLogger* ptr, bool* b) {
- *b = &logy == ptr;
-}
-
-void SomeLoggerMethCopy(CopyLogger logy, const CopyLogger* ptr, bool* b) {
- *b = &logy == ptr;
-}
-
-int CopyLogger::TimesCopied = 0;
-int CopyLogger::TimesConstructed = 0;
-
-} // namespace
-
-TEST(TupleTest, Copying) {
- CopyLogger logger;
- EXPECT_EQ(0, CopyLogger::TimesCopied);
- EXPECT_EQ(1, CopyLogger::TimesConstructed);
-
- bool res = false;
-
- // Creating the tuple should copy the class to store internally in the tuple.
- std::tuple<CopyLogger, CopyLogger*, bool*> tuple(logger, &logger, &res);
- std::get<CopyLogger*>(tuple) = &std::get<CopyLogger>(tuple);
- EXPECT_EQ(2, CopyLogger::TimesConstructed);
- EXPECT_EQ(1, CopyLogger::TimesCopied);
-
- // Our internal Logger and the one passed to the function should be the same.
- res = false;
- DispatchToFunction(&SomeLoggerMethRef, tuple);
- EXPECT_TRUE(res);
- EXPECT_EQ(2, CopyLogger::TimesConstructed);
- EXPECT_EQ(1, CopyLogger::TimesCopied);
-
- // Now they should be different, since the function call will make a copy.
- res = false;
- DispatchToFunction(&SomeLoggerMethCopy, tuple);
- EXPECT_FALSE(res);
- EXPECT_EQ(3, CopyLogger::TimesConstructed);
- EXPECT_EQ(2, CopyLogger::TimesCopied);
-}
-
-} // namespace base
diff --git a/base/unguessable_token_unittest.cc b/base/unguessable_token_unittest.cc
deleted file mode 100644
index b70cc72..0000000
--- 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_iterators_unittest.cc b/base/value_iterators_unittest.cc
deleted file mode 100644
index ed86182..0000000
--- a/base/value_iterators_unittest.cc
+++ /dev/null
@@ -1,335 +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/value_iterators.h"
-
-#include <type_traits>
-
-#include "base/memory/ptr_util.h"
-#include "base/values.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace detail {
-
-namespace {
-
-// Implementation of std::equal variant that is missing in C++11.
-template <class BinaryPredicate, class InputIterator1, class InputIterator2>
-bool are_equal(InputIterator1 first1,
- InputIterator1 last1,
- InputIterator2 first2,
- InputIterator2 last2,
- BinaryPredicate pred) {
- for (; first1 != last1 && first2 != last2; ++first1, ++first2) {
- if (!pred(*first1, *first2))
- return false;
- }
- return first1 == last1 && first2 == last2;
-}
-
-} // namespace
-
-TEST(ValueIteratorsTest, SameDictStorage) {
- static_assert(std::is_same<Value::DictStorage, DictStorage>::value,
- "DictStorage differs between Value and Value Iterators.");
-}
-
-TEST(ValueIteratorsTest, IsAssignable) {
- static_assert(
- !std::is_assignable<dict_iterator::reference::first_type, std::string>(),
- "Can assign strings to dict_iterator");
-
- static_assert(
- std::is_assignable<dict_iterator::reference::second_type, Value>(),
- "Can't assign Values to dict_iterator");
-
- static_assert(!std::is_assignable<const_dict_iterator::reference::first_type,
- std::string>(),
- "Can assign strings to const_dict_iterator");
-
- static_assert(
- !std::is_assignable<const_dict_iterator::reference::second_type, Value>(),
- "Can assign Values to const_dict_iterator");
-}
-
-TEST(ValueIteratorsTest, DictIteratorOperatorStar) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
-
- using iterator = dict_iterator;
- iterator iter(storage.begin());
- EXPECT_EQ("0", (*iter).first);
- EXPECT_EQ(Value(0), (*iter).second);
-
- (*iter).second = Value(1);
- EXPECT_EQ(Value(1), *storage["0"]);
-}
-
-TEST(ValueIteratorsTest, DictIteratorOperatorArrow) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
-
- using iterator = dict_iterator;
- iterator iter(storage.begin());
- EXPECT_EQ("0", iter->first);
- EXPECT_EQ(Value(0), iter->second);
-
- iter->second = Value(1);
- EXPECT_EQ(Value(1), *storage["0"]);
-}
-
-TEST(ValueIteratorsTest, DictIteratorPreIncrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = dict_iterator;
- iterator iter(storage.begin());
- EXPECT_EQ("0", iter->first);
- EXPECT_EQ(Value(0), iter->second);
-
- iterator& iter_ref = ++iter;
- EXPECT_EQ(&iter, &iter_ref);
-
- EXPECT_EQ("1", iter_ref->first);
- EXPECT_EQ(Value(1), iter_ref->second);
-}
-
-TEST(ValueIteratorsTest, DictIteratorPostIncrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = dict_iterator;
- iterator iter(storage.begin());
- iterator iter_old = iter++;
-
- EXPECT_EQ("0", iter_old->first);
- EXPECT_EQ(Value(0), iter_old->second);
-
- EXPECT_EQ("1", iter->first);
- EXPECT_EQ(Value(1), iter->second);
-}
-
-TEST(ValueIteratorsTest, DictIteratorPreDecrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = dict_iterator;
- iterator iter(++storage.begin());
- EXPECT_EQ("1", iter->first);
- EXPECT_EQ(Value(1), iter->second);
-
- iterator& iter_ref = --iter;
- EXPECT_EQ(&iter, &iter_ref);
-
- EXPECT_EQ("0", iter_ref->first);
- EXPECT_EQ(Value(0), iter_ref->second);
-}
-
-TEST(ValueIteratorsTest, DictIteratorPostDecrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = dict_iterator;
- iterator iter(++storage.begin());
- iterator iter_old = iter--;
-
- EXPECT_EQ("1", iter_old->first);
- EXPECT_EQ(Value(1), iter_old->second);
-
- EXPECT_EQ("0", iter->first);
- EXPECT_EQ(Value(0), iter->second);
-}
-
-TEST(ValueIteratorsTest, DictIteratorOperatorEQ) {
- DictStorage storage;
- using iterator = dict_iterator;
- EXPECT_EQ(iterator(storage.begin()), iterator(storage.begin()));
- EXPECT_EQ(iterator(storage.end()), iterator(storage.end()));
-}
-
-TEST(ValueIteratorsTest, DictIteratorOperatorNE) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
-
- using iterator = dict_iterator;
- EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorOperatorStar) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
-
- using iterator = const_dict_iterator;
- iterator iter(storage.begin());
- EXPECT_EQ("0", (*iter).first);
- EXPECT_EQ(Value(0), (*iter).second);
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorOperatorArrow) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
-
- using iterator = const_dict_iterator;
- iterator iter(storage.begin());
- EXPECT_EQ("0", iter->first);
- EXPECT_EQ(Value(0), iter->second);
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorPreIncrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = const_dict_iterator;
- iterator iter(storage.begin());
- EXPECT_EQ("0", iter->first);
- EXPECT_EQ(Value(0), iter->second);
-
- iterator& iter_ref = ++iter;
- EXPECT_EQ(&iter, &iter_ref);
-
- EXPECT_EQ("1", iter_ref->first);
- EXPECT_EQ(Value(1), iter_ref->second);
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorPostIncrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = const_dict_iterator;
- iterator iter(storage.begin());
- iterator iter_old = iter++;
-
- EXPECT_EQ("0", iter_old->first);
- EXPECT_EQ(Value(0), iter_old->second);
-
- EXPECT_EQ("1", iter->first);
- EXPECT_EQ(Value(1), iter->second);
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorPreDecrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = const_dict_iterator;
- iterator iter(++storage.begin());
- EXPECT_EQ("1", iter->first);
- EXPECT_EQ(Value(1), iter->second);
-
- iterator& iter_ref = --iter;
- EXPECT_EQ(&iter, &iter_ref);
-
- EXPECT_EQ("0", iter_ref->first);
- EXPECT_EQ(Value(0), iter_ref->second);
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorPostDecrement) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
- storage.emplace("1", std::make_unique<Value>(1));
-
- using iterator = const_dict_iterator;
- iterator iter(++storage.begin());
- iterator iter_old = iter--;
-
- EXPECT_EQ("1", iter_old->first);
- EXPECT_EQ(Value(1), iter_old->second);
-
- EXPECT_EQ("0", iter->first);
- EXPECT_EQ(Value(0), iter->second);
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorOperatorEQ) {
- DictStorage storage;
- using iterator = const_dict_iterator;
- EXPECT_EQ(iterator(storage.begin()), iterator(storage.begin()));
- EXPECT_EQ(iterator(storage.end()), iterator(storage.end()));
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorOperatorNE) {
- DictStorage storage;
- storage.emplace("0", std::make_unique<Value>(0));
-
- using iterator = const_dict_iterator;
- EXPECT_NE(iterator(storage.begin()), iterator(storage.end()));
-}
-
-TEST(ValueIteratorsTest, DictIteratorProxy) {
- DictStorage storage;
- storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
- storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
- storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
- storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
- storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
- storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
- storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
- storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
-
- using iterator = const_dict_iterator;
- using iterator_proxy = dict_iterator_proxy;
- iterator_proxy proxy(&storage);
-
- auto equal_to = [](const DictStorage::value_type& lhs,
- const iterator::reference& rhs) {
- return std::tie(lhs.first, *lhs.second) == std::tie(rhs.first, rhs.second);
- };
-
- EXPECT_TRUE(are_equal(storage.begin(), storage.end(), proxy.begin(),
- proxy.end(), equal_to));
-
- EXPECT_TRUE(are_equal(storage.rbegin(), storage.rend(), proxy.rbegin(),
- proxy.rend(), equal_to));
-
- EXPECT_TRUE(are_equal(storage.cbegin(), storage.cend(), proxy.cbegin(),
- proxy.cend(), equal_to));
-
- EXPECT_TRUE(are_equal(storage.crbegin(), storage.crend(), proxy.crbegin(),
- proxy.crend(), equal_to));
-}
-
-TEST(ValueIteratorsTest, ConstDictIteratorProxy) {
- DictStorage storage;
- storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
- storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
- storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
- storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
- storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
- storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
- storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
- storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
-
- using iterator = const_dict_iterator;
- using iterator_proxy = const_dict_iterator_proxy;
- iterator_proxy proxy(&storage);
-
- auto equal_to = [](const DictStorage::value_type& lhs,
- const iterator::reference& rhs) {
- return std::tie(lhs.first, *lhs.second) == std::tie(rhs.first, rhs.second);
- };
-
- EXPECT_TRUE(are_equal(storage.begin(), storage.end(), proxy.begin(),
- proxy.end(), equal_to));
-
- EXPECT_TRUE(are_equal(storage.rbegin(), storage.rend(), proxy.rbegin(),
- proxy.rend(), equal_to));
-
- EXPECT_TRUE(are_equal(storage.cbegin(), storage.cend(), proxy.cbegin(),
- proxy.cend(), equal_to));
-
- EXPECT_TRUE(are_equal(storage.crbegin(), storage.crend(), proxy.crbegin(),
- proxy.crend(), equal_to));
-}
-
-} // namespace detail
-
-} // namespace base
diff --git a/base/values_unittest.cc b/base/values_unittest.cc
deleted file mode 100644
index b8efac7..0000000
--- a/base/values_unittest.cc
+++ /dev/null
@@ -1,1922 +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/values.h"
-
-#include <stddef.h>
-
-#include <functional>
-#include <limits>
-#include <memory>
-#include <string>
-#include <type_traits>
-#include <utility>
-#include <vector>
-
-#include "base/containers/adapters.h"
-#include "base/memory/ptr_util.h"
-#include "base/strings/string16.h"
-#include "base/strings/string_piece.h"
-#include "base/strings/utf_string_conversions.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-TEST(ValuesTest, TestNothrow) {
- static_assert(std::is_nothrow_move_constructible<Value>::value,
- "IsNothrowMoveConstructible");
- static_assert(std::is_nothrow_default_constructible<Value>::value,
- "IsNothrowDefaultConstructible");
- static_assert(std::is_nothrow_constructible<Value, std::string&&>::value,
- "IsNothrowMoveConstructibleFromString");
- static_assert(
- std::is_nothrow_constructible<Value, Value::BlobStorage&&>::value,
- "IsNothrowMoveConstructibleFromBlob");
- static_assert(
- std::is_nothrow_constructible<Value, Value::ListStorage&&>::value,
- "IsNothrowMoveConstructibleFromList");
- static_assert(std::is_nothrow_move_assignable<Value>::value,
- "IsNothrowMoveAssignable");
- static_assert(
- std::is_nothrow_constructible<ListValue, Value::ListStorage&&>::value,
- "ListIsNothrowMoveConstructibleFromList");
-}
-
-// Group of tests for the value constructors.
-TEST(ValuesTest, ConstructBool) {
- Value true_value(true);
- EXPECT_EQ(Value::Type::BOOLEAN, true_value.type());
- EXPECT_TRUE(true_value.GetBool());
-
- Value false_value(false);
- EXPECT_EQ(Value::Type::BOOLEAN, false_value.type());
- EXPECT_FALSE(false_value.GetBool());
-}
-
-TEST(ValuesTest, ConstructInt) {
- Value value(-37);
- EXPECT_EQ(Value::Type::INTEGER, value.type());
- EXPECT_EQ(-37, value.GetInt());
-}
-
-TEST(ValuesTest, ConstructDouble) {
- Value value(-4.655);
- EXPECT_EQ(Value::Type::DOUBLE, value.type());
- EXPECT_EQ(-4.655, value.GetDouble());
-}
-
-TEST(ValuesTest, ConstructStringFromConstCharPtr) {
- const char* str = "foobar";
- Value value(str);
- EXPECT_EQ(Value::Type::STRING, value.type());
- EXPECT_EQ("foobar", value.GetString());
-}
-
-TEST(ValuesTest, ConstructStringFromStringPiece) {
- std::string str = "foobar";
- Value value{StringPiece(str)};
- EXPECT_EQ(Value::Type::STRING, value.type());
- EXPECT_EQ("foobar", value.GetString());
-}
-
-TEST(ValuesTest, ConstructStringFromStdStringRRef) {
- std::string str = "foobar";
- Value value(std::move(str));
- EXPECT_EQ(Value::Type::STRING, value.type());
- EXPECT_EQ("foobar", value.GetString());
-}
-
-TEST(ValuesTest, ConstructStringFromConstChar16Ptr) {
- string16 str = ASCIIToUTF16("foobar");
- Value value(str.c_str());
- EXPECT_EQ(Value::Type::STRING, value.type());
- EXPECT_EQ("foobar", value.GetString());
-}
-
-TEST(ValuesTest, ConstructStringFromStringPiece16) {
- string16 str = ASCIIToUTF16("foobar");
- Value value{StringPiece16(str)};
- EXPECT_EQ(Value::Type::STRING, value.type());
- EXPECT_EQ("foobar", value.GetString());
-}
-
-TEST(ValuesTest, ConstructBinary) {
- Value value(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
- EXPECT_EQ(Value::Type::BINARY, value.type());
- EXPECT_EQ(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}),
- value.GetBlob());
-}
-
-TEST(ValuesTest, ConstructDict) {
- DictionaryValue value;
- EXPECT_EQ(Value::Type::DICTIONARY, value.type());
-}
-
-TEST(ValuesTest, ConstructDictFromStorage) {
- Value::DictStorage storage;
- storage.emplace("foo", std::make_unique<Value>("bar"));
- {
- DictionaryValue value(storage);
- EXPECT_EQ(Value::Type::DICTIONARY, value.type());
- EXPECT_EQ(Value::Type::STRING, value.FindKey("foo")->type());
- EXPECT_EQ("bar", value.FindKey("foo")->GetString());
- }
-
- *storage["foo"] = base::Value("baz");
- {
- DictionaryValue value(std::move(storage));
- EXPECT_EQ(Value::Type::DICTIONARY, value.type());
- EXPECT_EQ(Value::Type::STRING, value.FindKey("foo")->type());
- EXPECT_EQ("baz", value.FindKey("foo")->GetString());
- }
-}
-
-TEST(ValuesTest, ConstructList) {
- ListValue value;
- EXPECT_EQ(Value::Type::LIST, value.type());
-}
-
-TEST(ValuesTest, ConstructListFromStorage) {
- Value::ListStorage storage;
- storage.emplace_back("foo");
- {
- ListValue value(storage);
- EXPECT_EQ(Value::Type::LIST, value.type());
- EXPECT_EQ(1u, value.GetList().size());
- EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
- EXPECT_EQ("foo", value.GetList()[0].GetString());
- }
-
- storage.back() = base::Value("bar");
- {
- ListValue value(std::move(storage));
- EXPECT_EQ(Value::Type::LIST, value.type());
- EXPECT_EQ(1u, value.GetList().size());
- EXPECT_EQ(Value::Type::STRING, value.GetList()[0].type());
- EXPECT_EQ("bar", value.GetList()[0].GetString());
- }
-}
-
-// Group of tests for the copy constructors and copy-assigmnent. For equality
-// checks comparisons of the interesting fields are done instead of relying on
-// Equals being correct.
-TEST(ValuesTest, CopyBool) {
- Value true_value(true);
- Value copied_true_value(true_value.Clone());
- EXPECT_EQ(true_value.type(), copied_true_value.type());
- EXPECT_EQ(true_value.GetBool(), copied_true_value.GetBool());
-
- Value false_value(false);
- Value copied_false_value(false_value.Clone());
- EXPECT_EQ(false_value.type(), copied_false_value.type());
- EXPECT_EQ(false_value.GetBool(), copied_false_value.GetBool());
-
- Value blank;
-
- blank = true_value.Clone();
- EXPECT_EQ(true_value.type(), blank.type());
- EXPECT_EQ(true_value.GetBool(), blank.GetBool());
-
- blank = false_value.Clone();
- EXPECT_EQ(false_value.type(), blank.type());
- EXPECT_EQ(false_value.GetBool(), blank.GetBool());
-}
-
-TEST(ValuesTest, CopyInt) {
- Value value(74);
- Value copied_value(value.Clone());
- EXPECT_EQ(value.type(), copied_value.type());
- EXPECT_EQ(value.GetInt(), copied_value.GetInt());
-
- Value blank;
-
- blank = value.Clone();
- EXPECT_EQ(value.type(), blank.type());
- EXPECT_EQ(value.GetInt(), blank.GetInt());
-}
-
-TEST(ValuesTest, CopyDouble) {
- Value value(74.896);
- Value copied_value(value.Clone());
- EXPECT_EQ(value.type(), copied_value.type());
- EXPECT_EQ(value.GetDouble(), copied_value.GetDouble());
-
- Value blank;
-
- blank = value.Clone();
- EXPECT_EQ(value.type(), blank.type());
- EXPECT_EQ(value.GetDouble(), blank.GetDouble());
-}
-
-TEST(ValuesTest, CopyString) {
- Value value("foobar");
- Value copied_value(value.Clone());
- EXPECT_EQ(value.type(), copied_value.type());
- EXPECT_EQ(value.GetString(), copied_value.GetString());
-
- Value blank;
-
- blank = value.Clone();
- EXPECT_EQ(value.type(), blank.type());
- EXPECT_EQ(value.GetString(), blank.GetString());
-}
-
-TEST(ValuesTest, CopyBinary) {
- Value value(Value::BlobStorage({0xF, 0x0, 0x0, 0xB, 0xA, 0x2}));
- Value copied_value(value.Clone());
- EXPECT_EQ(value.type(), copied_value.type());
- EXPECT_EQ(value.GetBlob(), copied_value.GetBlob());
-
- Value blank;
-
- blank = value.Clone();
- EXPECT_EQ(value.type(), blank.type());
- EXPECT_EQ(value.GetBlob(), blank.GetBlob());
-}
-
-TEST(ValuesTest, CopyDictionary) {
- Value::DictStorage storage;
- storage.emplace("Int", std::make_unique<Value>(123));
- Value value(std::move(storage));
-
- Value copied_value(value.Clone());
- EXPECT_EQ(value, copied_value);
-
- Value blank;
- blank = value.Clone();
- EXPECT_EQ(value, blank);
-}
-
-TEST(ValuesTest, CopyList) {
- Value::ListStorage storage;
- storage.emplace_back(123);
- Value value(std::move(storage));
-
- Value copied_value(value.Clone());
- EXPECT_EQ(value, copied_value);
-
- Value blank;
- blank = value.Clone();
- EXPECT_EQ(value, blank);
-}
-
-// Group of tests for the move constructors and move-assigmnent.
-TEST(ValuesTest, MoveBool) {
- Value true_value(true);
- Value moved_true_value(std::move(true_value));
- EXPECT_EQ(Value::Type::BOOLEAN, moved_true_value.type());
- EXPECT_TRUE(moved_true_value.GetBool());
-
- Value false_value(false);
- Value moved_false_value(std::move(false_value));
- EXPECT_EQ(Value::Type::BOOLEAN, moved_false_value.type());
- EXPECT_FALSE(moved_false_value.GetBool());
-
- Value blank;
-
- blank = Value(true);
- EXPECT_EQ(Value::Type::BOOLEAN, blank.type());
- EXPECT_TRUE(blank.GetBool());
-
- blank = Value(false);
- EXPECT_EQ(Value::Type::BOOLEAN, blank.type());
- EXPECT_FALSE(blank.GetBool());
-}
-
-TEST(ValuesTest, MoveInt) {
- Value value(74);
- Value moved_value(std::move(value));
- EXPECT_EQ(Value::Type::INTEGER, moved_value.type());
- EXPECT_EQ(74, moved_value.GetInt());
-
- Value blank;
-
- blank = Value(47);
- EXPECT_EQ(Value::Type::INTEGER, blank.type());
- EXPECT_EQ(47, blank.GetInt());
-}
-
-TEST(ValuesTest, MoveDouble) {
- Value value(74.896);
- Value moved_value(std::move(value));
- EXPECT_EQ(Value::Type::DOUBLE, moved_value.type());
- EXPECT_EQ(74.896, moved_value.GetDouble());
-
- Value blank;
-
- blank = Value(654.38);
- EXPECT_EQ(Value::Type::DOUBLE, blank.type());
- EXPECT_EQ(654.38, blank.GetDouble());
-}
-
-TEST(ValuesTest, MoveString) {
- Value value("foobar");
- Value moved_value(std::move(value));
- EXPECT_EQ(Value::Type::STRING, moved_value.type());
- EXPECT_EQ("foobar", moved_value.GetString());
-
- Value blank;
-
- blank = Value("foobar");
- EXPECT_EQ(Value::Type::STRING, blank.type());
- EXPECT_EQ("foobar", blank.GetString());
-}
-
-TEST(ValuesTest, MoveBinary) {
- const Value::BlobStorage buffer = {0xF, 0x0, 0x0, 0xB, 0xA, 0x2};
- Value value(buffer);
- Value moved_value(std::move(value));
- EXPECT_EQ(Value::Type::BINARY, moved_value.type());
- EXPECT_EQ(buffer, moved_value.GetBlob());
-
- Value blank;
-
- blank = Value(buffer);
- EXPECT_EQ(Value::Type::BINARY, blank.type());
- EXPECT_EQ(buffer, blank.GetBlob());
-}
-
-TEST(ValuesTest, MoveConstructDictionary) {
- Value::DictStorage storage;
- storage.emplace("Int", std::make_unique<Value>(123));
-
- Value value(std::move(storage));
- Value moved_value(std::move(value));
- EXPECT_EQ(Value::Type::DICTIONARY, moved_value.type());
- EXPECT_EQ(123, moved_value.FindKey("Int")->GetInt());
-}
-
-TEST(ValuesTest, MoveAssignDictionary) {
- Value::DictStorage storage;
- storage.emplace("Int", std::make_unique<Value>(123));
-
- Value blank;
- blank = Value(std::move(storage));
- EXPECT_EQ(Value::Type::DICTIONARY, blank.type());
- EXPECT_EQ(123, blank.FindKey("Int")->GetInt());
-}
-
-TEST(ValuesTest, MoveList) {
- Value::ListStorage storage;
- storage.emplace_back(123);
- Value value(storage);
- Value moved_value(std::move(value));
- EXPECT_EQ(Value::Type::LIST, moved_value.type());
- EXPECT_EQ(123, moved_value.GetList().back().GetInt());
-
- Value blank;
- blank = Value(std::move(storage));
- EXPECT_EQ(Value::Type::LIST, blank.type());
- EXPECT_EQ(123, blank.GetList().back().GetInt());
-}
-
-TEST(ValuesTest, FindKey) {
- Value::DictStorage storage;
- storage.emplace("foo", std::make_unique<Value>("bar"));
- Value dict(std::move(storage));
- EXPECT_NE(nullptr, dict.FindKey("foo"));
- EXPECT_EQ(nullptr, dict.FindKey("baz"));
-
- // Single not found key.
- bool found = dict.FindKey("notfound");
- EXPECT_FALSE(found);
-}
-
-TEST(ValuesTest, FindKeyChangeValue) {
- Value::DictStorage storage;
- storage.emplace("foo", std::make_unique<Value>("bar"));
- Value dict(std::move(storage));
- Value* found = dict.FindKey("foo");
- EXPECT_NE(nullptr, found);
- EXPECT_EQ("bar", found->GetString());
-
- *found = Value(123);
- EXPECT_EQ(123, dict.FindKey("foo")->GetInt());
-}
-
-TEST(ValuesTest, FindKeyConst) {
- Value::DictStorage storage;
- storage.emplace("foo", std::make_unique<Value>("bar"));
- const Value dict(std::move(storage));
- EXPECT_NE(nullptr, dict.FindKey("foo"));
- EXPECT_EQ(nullptr, dict.FindKey("baz"));
-}
-
-TEST(ValuesTest, FindKeyOfType) {
- Value::DictStorage storage;
- storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
- storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
- storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
- storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
- storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
- storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
- storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
- storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
-
- Value dict(std::move(storage));
- EXPECT_NE(nullptr, dict.FindKeyOfType("null", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::NONE));
- EXPECT_NE(nullptr, dict.FindKeyOfType("bool", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BOOLEAN));
- EXPECT_NE(nullptr, dict.FindKeyOfType("int", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::INTEGER));
- EXPECT_NE(nullptr, dict.FindKeyOfType("double", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DOUBLE));
- EXPECT_NE(nullptr, dict.FindKeyOfType("string", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::STRING));
- EXPECT_NE(nullptr, dict.FindKeyOfType("blob", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BINARY));
- EXPECT_NE(nullptr, dict.FindKeyOfType("list", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::LIST));
- EXPECT_NE(nullptr, dict.FindKeyOfType("dict", Value::Type::DICTIONARY));
-}
-
-TEST(ValuesTest, FindKeyOfTypeConst) {
- Value::DictStorage storage;
- storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
- storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
- storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
- storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
- storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
- storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
- storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
- storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
-
- const Value dict(std::move(storage));
- EXPECT_NE(nullptr, dict.FindKeyOfType("null", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("null", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::NONE));
- EXPECT_NE(nullptr, dict.FindKeyOfType("bool", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("bool", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BOOLEAN));
- EXPECT_NE(nullptr, dict.FindKeyOfType("int", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("int", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::INTEGER));
- EXPECT_NE(nullptr, dict.FindKeyOfType("double", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("double", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DOUBLE));
- EXPECT_NE(nullptr, dict.FindKeyOfType("string", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("string", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::STRING));
- EXPECT_NE(nullptr, dict.FindKeyOfType("blob", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("blob", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::BINARY));
- EXPECT_NE(nullptr, dict.FindKeyOfType("list", Value::Type::LIST));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("list", Value::Type::DICTIONARY));
-
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::NONE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BOOLEAN));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::INTEGER));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::DOUBLE));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::STRING));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::BINARY));
- EXPECT_EQ(nullptr, dict.FindKeyOfType("dict", Value::Type::LIST));
- EXPECT_NE(nullptr, dict.FindKeyOfType("dict", Value::Type::DICTIONARY));
-}
-
-TEST(ValuesTest, SetKey) {
- Value::DictStorage storage;
- storage.emplace("null", std::make_unique<Value>(Value::Type::NONE));
- storage.emplace("bool", std::make_unique<Value>(Value::Type::BOOLEAN));
- storage.emplace("int", std::make_unique<Value>(Value::Type::INTEGER));
- storage.emplace("double", std::make_unique<Value>(Value::Type::DOUBLE));
- storage.emplace("string", std::make_unique<Value>(Value::Type::STRING));
- storage.emplace("blob", std::make_unique<Value>(Value::Type::BINARY));
- storage.emplace("list", std::make_unique<Value>(Value::Type::LIST));
- storage.emplace("dict", std::make_unique<Value>(Value::Type::DICTIONARY));
-
- Value dict(Value::Type::DICTIONARY);
- dict.SetKey(StringPiece("null"), Value(Value::Type::NONE));
- dict.SetKey(StringPiece("bool"), Value(Value::Type::BOOLEAN));
- dict.SetKey(std::string("int"), Value(Value::Type::INTEGER));
- dict.SetKey(std::string("double"), Value(Value::Type::DOUBLE));
- dict.SetKey(std::string("string"), Value(Value::Type::STRING));
- dict.SetKey("blob", Value(Value::Type::BINARY));
- dict.SetKey("list", Value(Value::Type::LIST));
- dict.SetKey("dict", Value(Value::Type::DICTIONARY));
-
- EXPECT_EQ(Value(std::move(storage)), dict);
-}
-
-TEST(ValuesTest, FindPath) {
- // Construct a dictionary path {root}.foo.bar = 123
- Value foo(Value::Type::DICTIONARY);
- foo.SetKey("bar", Value(123));
-
- Value root(Value::Type::DICTIONARY);
- root.SetKey("foo", std::move(foo));
-
- // No key (stupid but well-defined and takes work to prevent).
- Value* found = root.FindPath(std::vector<StringPiece>{});
- EXPECT_EQ(&root, found);
-
- // Double key, second not found.
- found = root.FindPath(std::vector<StringPiece>{"foo", "notfound"});
- EXPECT_FALSE(found);
-
- // Double key, found.
- found = root.FindPath(std::vector<StringPiece>{"foo", "bar"});
- EXPECT_TRUE(found);
- EXPECT_TRUE(found->is_int());
- EXPECT_EQ(123, found->GetInt());
-}
-
-TEST(ValuesTest, SetPath) {
- Value root(Value::Type::DICTIONARY);
-
- Value* inserted = root.SetPath({"one", "two"}, Value(123));
- Value* found = root.FindPathOfType({"one", "two"}, Value::Type::INTEGER);
- ASSERT_TRUE(found);
- EXPECT_EQ(inserted, found);
- EXPECT_EQ(123, found->GetInt());
-
- inserted = root.SetPath(std::vector<StringPiece>{"foo", "bar"}, Value(123));
- found = root.FindPathOfType({"foo", "bar"}, Value::Type::INTEGER);
- ASSERT_TRUE(found);
- EXPECT_EQ(inserted, found);
- EXPECT_EQ(123, found->GetInt());
-
- // Overwrite with a different value.
- root.SetPath({"foo", "bar"}, Value("hello"));
- found = root.FindPathOfType(std::vector<StringPiece>{"foo", "bar"},
- Value::Type::STRING);
- ASSERT_TRUE(found);
- EXPECT_EQ("hello", found->GetString());
-
- // Can't change existing non-dictionary keys to dictionaries.
- found =
- root.SetPath(std::vector<StringPiece>{"foo", "bar", "baz"}, Value(123));
- EXPECT_FALSE(found);
-}
-
-TEST(ValuesTest, RemoveKey) {
- Value root(Value::Type::DICTIONARY);
- root.SetKey("one", Value(123));
-
- // Removal of missing key should fail.
- EXPECT_FALSE(root.RemoveKey("two"));
-
- // Removal of existing key should succeed.
- EXPECT_TRUE(root.RemoveKey("one"));
-
- // Second removal of previously existing key should fail.
- EXPECT_FALSE(root.RemoveKey("one"));
-}
-
-TEST(ValuesTest, RemovePath) {
- Value root(Value::Type::DICTIONARY);
- root.SetPath({"one", "two", "three"}, Value(123));
-
- // Removal of missing key should fail.
- EXPECT_FALSE(root.RemovePath({"one", "two", "four"}));
-
- // Removal of existing key should succeed.
- EXPECT_TRUE(root.RemovePath({"one", "two", "three"}));
-
- // Second removal of previously existing key should fail.
- EXPECT_FALSE(root.RemovePath({"one", "two", "three"}));
-
- // Intermediate empty dictionaries should be cleared.
- EXPECT_FALSE(root.FindKey("one"));
-
- root.SetPath({"one", "two", "three"}, Value(123));
- root.SetPath({"one", "two", "four"}, Value(124));
-
- EXPECT_TRUE(root.RemovePath(std::vector<StringPiece>{"one", "two", "three"}));
- // Intermediate non-empty dictionaries should be kept.
- EXPECT_TRUE(root.FindKey("one"));
- EXPECT_TRUE(root.FindPath({"one", "two"}));
- EXPECT_TRUE(root.FindPath({"one", "two", "four"}));
-}
-
-TEST(ValuesTest, Basic) {
- // Test basic dictionary getting/setting
- DictionaryValue settings;
- std::string homepage = "http://google.com";
- ASSERT_FALSE(settings.GetString("global.homepage", &homepage));
- ASSERT_EQ(std::string("http://google.com"), homepage);
-
- ASSERT_FALSE(settings.Get("global", nullptr));
- settings.SetBoolean("global", true);
- ASSERT_TRUE(settings.Get("global", nullptr));
- settings.SetString("global.homepage", "http://scurvy.com");
- ASSERT_TRUE(settings.Get("global", nullptr));
- homepage = "http://google.com";
- ASSERT_TRUE(settings.GetString("global.homepage", &homepage));
- ASSERT_EQ(std::string("http://scurvy.com"), homepage);
-
- // Test storing a dictionary in a list.
- ListValue* toolbar_bookmarks;
- ASSERT_FALSE(
- settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks));
-
- std::unique_ptr<ListValue> new_toolbar_bookmarks(new ListValue);
- settings.Set("global.toolbar.bookmarks", std::move(new_toolbar_bookmarks));
- ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &toolbar_bookmarks));
-
- std::unique_ptr<DictionaryValue> new_bookmark(new DictionaryValue);
- new_bookmark->SetString("name", "Froogle");
- new_bookmark->SetString("url", "http://froogle.com");
- toolbar_bookmarks->Append(std::move(new_bookmark));
-
- ListValue* bookmark_list;
- ASSERT_TRUE(settings.GetList("global.toolbar.bookmarks", &bookmark_list));
- DictionaryValue* bookmark;
- ASSERT_EQ(1U, bookmark_list->GetSize());
- ASSERT_TRUE(bookmark_list->GetDictionary(0, &bookmark));
- std::string bookmark_name = "Unnamed";
- ASSERT_TRUE(bookmark->GetString("name", &bookmark_name));
- ASSERT_EQ(std::string("Froogle"), bookmark_name);
- std::string bookmark_url;
- ASSERT_TRUE(bookmark->GetString("url", &bookmark_url));
- ASSERT_EQ(std::string("http://froogle.com"), bookmark_url);
-}
-
-TEST(ValuesTest, List) {
- std::unique_ptr<ListValue> mixed_list(new ListValue());
- mixed_list->Set(0, std::make_unique<Value>(true));
- mixed_list->Set(1, std::make_unique<Value>(42));
- mixed_list->Set(2, std::make_unique<Value>(88.8));
- mixed_list->Set(3, std::make_unique<Value>("foo"));
- ASSERT_EQ(4u, mixed_list->GetSize());
-
- Value* value = nullptr;
- bool bool_value = false;
- int int_value = 0;
- double double_value = 0.0;
- std::string string_value;
-
- ASSERT_FALSE(mixed_list->Get(4, &value));
-
- ASSERT_FALSE(mixed_list->GetInteger(0, &int_value));
- ASSERT_EQ(0, int_value);
- ASSERT_FALSE(mixed_list->GetBoolean(1, &bool_value));
- ASSERT_FALSE(bool_value);
- ASSERT_FALSE(mixed_list->GetString(2, &string_value));
- ASSERT_EQ("", string_value);
- ASSERT_FALSE(mixed_list->GetInteger(2, &int_value));
- ASSERT_EQ(0, int_value);
- ASSERT_FALSE(mixed_list->GetBoolean(3, &bool_value));
- ASSERT_FALSE(bool_value);
-
- ASSERT_TRUE(mixed_list->GetBoolean(0, &bool_value));
- ASSERT_TRUE(bool_value);
- ASSERT_TRUE(mixed_list->GetInteger(1, &int_value));
- ASSERT_EQ(42, int_value);
- // implicit conversion from Integer to Double should be possible.
- ASSERT_TRUE(mixed_list->GetDouble(1, &double_value));
- ASSERT_EQ(42, double_value);
- ASSERT_TRUE(mixed_list->GetDouble(2, &double_value));
- ASSERT_EQ(88.8, double_value);
- ASSERT_TRUE(mixed_list->GetString(3, &string_value));
- ASSERT_EQ("foo", string_value);
-
- // Try searching in the mixed list.
- base::Value sought_value(42);
- base::Value not_found_value(false);
-
- ASSERT_NE(mixed_list->end(), mixed_list->Find(sought_value));
- ASSERT_TRUE((*mixed_list->Find(sought_value)).GetAsInteger(&int_value));
- ASSERT_EQ(42, int_value);
- ASSERT_EQ(mixed_list->end(), mixed_list->Find(not_found_value));
-}
-
-TEST(ValuesTest, BinaryValue) {
- // Default constructor creates a BinaryValue with a buffer of size 0.
- auto binary = std::make_unique<Value>(Value::Type::BINARY);
- ASSERT_TRUE(binary.get());
- ASSERT_TRUE(binary->GetBlob().empty());
-
- // Test the common case of a non-empty buffer
- Value::BlobStorage buffer(15);
- char* original_buffer = buffer.data();
- binary.reset(new Value(std::move(buffer)));
- ASSERT_TRUE(binary.get());
- ASSERT_TRUE(binary->GetBlob().data());
- ASSERT_EQ(original_buffer, binary->GetBlob().data());
- ASSERT_EQ(15U, binary->GetBlob().size());
-
- char stack_buffer[42];
- memset(stack_buffer, '!', 42);
- binary = Value::CreateWithCopiedBuffer(stack_buffer, 42);
- ASSERT_TRUE(binary.get());
- ASSERT_TRUE(binary->GetBlob().data());
- ASSERT_NE(stack_buffer, binary->GetBlob().data());
- ASSERT_EQ(42U, binary->GetBlob().size());
- ASSERT_EQ(0, memcmp(stack_buffer, binary->GetBlob().data(),
- binary->GetBlob().size()));
-}
-
-TEST(ValuesTest, StringValue) {
- // Test overloaded StringValue constructor.
- std::unique_ptr<Value> narrow_value(new Value("narrow"));
- ASSERT_TRUE(narrow_value.get());
- ASSERT_TRUE(narrow_value->is_string());
- std::unique_ptr<Value> utf16_value(new Value(ASCIIToUTF16("utf16")));
- ASSERT_TRUE(utf16_value.get());
- ASSERT_TRUE(utf16_value->is_string());
-
- // Test overloaded GetAsString.
- std::string narrow = "http://google.com";
- string16 utf16 = ASCIIToUTF16("http://google.com");
- const Value* string_value = nullptr;
- ASSERT_TRUE(narrow_value->GetAsString(&narrow));
- ASSERT_TRUE(narrow_value->GetAsString(&utf16));
- ASSERT_TRUE(narrow_value->GetAsString(&string_value));
- ASSERT_EQ(std::string("narrow"), narrow);
- ASSERT_EQ(ASCIIToUTF16("narrow"), utf16);
- ASSERT_EQ(string_value->GetString(), narrow);
-
- ASSERT_TRUE(utf16_value->GetAsString(&narrow));
- ASSERT_TRUE(utf16_value->GetAsString(&utf16));
- ASSERT_TRUE(utf16_value->GetAsString(&string_value));
- ASSERT_EQ(std::string("utf16"), narrow);
- ASSERT_EQ(ASCIIToUTF16("utf16"), utf16);
- ASSERT_EQ(string_value->GetString(), narrow);
-
- // Don't choke on NULL values.
- ASSERT_TRUE(narrow_value->GetAsString(static_cast<string16*>(nullptr)));
- ASSERT_TRUE(narrow_value->GetAsString(static_cast<std::string*>(nullptr)));
- ASSERT_TRUE(narrow_value->GetAsString(static_cast<const Value**>(nullptr)));
-}
-
-TEST(ValuesTest, ListDeletion) {
- ListValue list;
- list.Append(std::make_unique<Value>());
- EXPECT_FALSE(list.empty());
- list.Clear();
- EXPECT_TRUE(list.empty());
-}
-
-TEST(ValuesTest, ListRemoval) {
- std::unique_ptr<Value> removed_item;
-
- {
- ListValue list;
- list.Append(std::make_unique<Value>());
- EXPECT_EQ(1U, list.GetSize());
- EXPECT_FALSE(list.Remove(std::numeric_limits<size_t>::max(),
- &removed_item));
- EXPECT_FALSE(list.Remove(1, &removed_item));
- EXPECT_TRUE(list.Remove(0, &removed_item));
- ASSERT_TRUE(removed_item);
- EXPECT_EQ(0U, list.GetSize());
- }
- removed_item.reset();
-
- {
- ListValue list;
- list.Append(std::make_unique<Value>());
- EXPECT_TRUE(list.Remove(0, nullptr));
- EXPECT_EQ(0U, list.GetSize());
- }
-
- {
- ListValue list;
- auto value = std::make_unique<Value>();
- Value original_value = value->Clone();
- list.Append(std::move(value));
- size_t index = 0;
- list.Remove(original_value, &index);
- EXPECT_EQ(0U, index);
- EXPECT_EQ(0U, list.GetSize());
- }
-}
-
-TEST(ValuesTest, DictionaryDeletion) {
- std::string key = "test";
- DictionaryValue dict;
- dict.Set(key, std::make_unique<Value>());
- EXPECT_FALSE(dict.empty());
- EXPECT_FALSE(dict.DictEmpty());
- EXPECT_EQ(1U, dict.DictSize());
- dict.Clear();
- EXPECT_TRUE(dict.empty());
- EXPECT_TRUE(dict.DictEmpty());
- EXPECT_EQ(0U, dict.DictSize());
-}
-
-TEST(ValuesTest, DictionarySetReturnsPointer) {
- {
- DictionaryValue dict;
- Value* blank_ptr = dict.Set("foo.bar", std::make_unique<base::Value>());
- EXPECT_EQ(Value::Type::NONE, blank_ptr->type());
- }
-
- {
- DictionaryValue dict;
- Value* blank_ptr = dict.SetWithoutPathExpansion(
- "foo.bar", std::make_unique<base::Value>());
- EXPECT_EQ(Value::Type::NONE, blank_ptr->type());
- }
-
- {
- DictionaryValue dict;
- Value* int_ptr = dict.SetInteger("foo.bar", 42);
- EXPECT_EQ(Value::Type::INTEGER, int_ptr->type());
- EXPECT_EQ(42, int_ptr->GetInt());
- }
-
- {
- DictionaryValue dict;
- Value* double_ptr = dict.SetDouble("foo.bar", 3.142);
- EXPECT_EQ(Value::Type::DOUBLE, double_ptr->type());
- EXPECT_EQ(3.142, double_ptr->GetDouble());
- }
-
- {
- DictionaryValue dict;
- Value* string_ptr = dict.SetString("foo.bar", "foo");
- EXPECT_EQ(Value::Type::STRING, string_ptr->type());
- EXPECT_EQ("foo", string_ptr->GetString());
- }
-
- {
- DictionaryValue dict;
- Value* string16_ptr = dict.SetString("foo.bar", ASCIIToUTF16("baz"));
- EXPECT_EQ(Value::Type::STRING, string16_ptr->type());
- EXPECT_EQ("baz", string16_ptr->GetString());
- }
-
- {
- DictionaryValue dict;
- DictionaryValue* dict_ptr = dict.SetDictionary(
- "foo.bar", std::make_unique<base::DictionaryValue>());
- EXPECT_EQ(Value::Type::DICTIONARY, dict_ptr->type());
- }
-
- {
- DictionaryValue dict;
- ListValue* list_ptr =
- dict.SetList("foo.bar", std::make_unique<base::ListValue>());
- EXPECT_EQ(Value::Type::LIST, list_ptr->type());
- }
-}
-
-TEST(ValuesTest, DictionaryRemoval) {
- std::string key = "test";
- std::unique_ptr<Value> removed_item;
-
- {
- DictionaryValue dict;
- EXPECT_EQ(0U, dict.DictSize());
- EXPECT_TRUE(dict.DictEmpty());
- dict.Set(key, std::make_unique<Value>());
- EXPECT_TRUE(dict.HasKey(key));
- EXPECT_FALSE(dict.Remove("absent key", &removed_item));
- EXPECT_EQ(1U, dict.DictSize());
- EXPECT_FALSE(dict.DictEmpty());
-
- EXPECT_TRUE(dict.Remove(key, &removed_item));
- EXPECT_FALSE(dict.HasKey(key));
- ASSERT_TRUE(removed_item);
- EXPECT_EQ(0U, dict.DictSize());
- EXPECT_TRUE(dict.DictEmpty());
- }
-
- {
- DictionaryValue dict;
- dict.Set(key, std::make_unique<Value>());
- EXPECT_TRUE(dict.HasKey(key));
- EXPECT_TRUE(dict.Remove(key, nullptr));
- EXPECT_FALSE(dict.HasKey(key));
- }
-}
-
-TEST(ValuesTest, DictionaryWithoutPathExpansion) {
- DictionaryValue dict;
- dict.Set("this.is.expanded", std::make_unique<Value>());
- dict.SetWithoutPathExpansion("this.isnt.expanded", std::make_unique<Value>());
-
- EXPECT_FALSE(dict.HasKey("this.is.expanded"));
- EXPECT_TRUE(dict.HasKey("this"));
- Value* value1;
- EXPECT_TRUE(dict.Get("this", &value1));
- DictionaryValue* value2;
- ASSERT_TRUE(dict.GetDictionaryWithoutPathExpansion("this", &value2));
- EXPECT_EQ(value1, value2);
- EXPECT_EQ(1U, value2->size());
-
- EXPECT_TRUE(dict.HasKey("this.isnt.expanded"));
- Value* value3;
- EXPECT_FALSE(dict.Get("this.isnt.expanded", &value3));
- Value* value4;
- ASSERT_TRUE(dict.GetWithoutPathExpansion("this.isnt.expanded", &value4));
- EXPECT_EQ(Value::Type::NONE, value4->type());
-}
-
-// Tests the deprecated version of SetWithoutPathExpansion.
-// TODO(estade): remove.
-TEST(ValuesTest, DictionaryWithoutPathExpansionDeprecated) {
- DictionaryValue dict;
- dict.Set("this.is.expanded", std::make_unique<Value>());
- dict.SetWithoutPathExpansion("this.isnt.expanded", std::make_unique<Value>());
-
- EXPECT_FALSE(dict.HasKey("this.is.expanded"));
- EXPECT_TRUE(dict.HasKey("this"));
- Value* value1;
- EXPECT_TRUE(dict.Get("this", &value1));
- DictionaryValue* value2;
- ASSERT_TRUE(dict.GetDictionaryWithoutPathExpansion("this", &value2));
- EXPECT_EQ(value1, value2);
- EXPECT_EQ(1U, value2->size());
-
- EXPECT_TRUE(dict.HasKey("this.isnt.expanded"));
- Value* value3;
- EXPECT_FALSE(dict.Get("this.isnt.expanded", &value3));
- Value* value4;
- ASSERT_TRUE(dict.GetWithoutPathExpansion("this.isnt.expanded", &value4));
- EXPECT_EQ(Value::Type::NONE, value4->type());
-}
-
-TEST(ValuesTest, DictionaryRemovePath) {
- DictionaryValue dict;
- dict.SetInteger("a.long.way.down", 1);
- dict.SetBoolean("a.long.key.path", true);
-
- std::unique_ptr<Value> removed_item;
- EXPECT_TRUE(dict.RemovePath("a.long.way.down", &removed_item));
- ASSERT_TRUE(removed_item);
- EXPECT_TRUE(removed_item->is_int());
- EXPECT_FALSE(dict.HasKey("a.long.way.down"));
- EXPECT_FALSE(dict.HasKey("a.long.way"));
- EXPECT_TRUE(dict.Get("a.long.key.path", nullptr));
-
- removed_item.reset();
- EXPECT_FALSE(dict.RemovePath("a.long.way.down", &removed_item));
- EXPECT_FALSE(removed_item);
- EXPECT_TRUE(dict.Get("a.long.key.path", nullptr));
-
- removed_item.reset();
- EXPECT_TRUE(dict.RemovePath("a.long.key.path", &removed_item));
- ASSERT_TRUE(removed_item);
- EXPECT_TRUE(removed_item->is_bool());
- EXPECT_TRUE(dict.empty());
-}
-
-TEST(ValuesTest, DeepCopy) {
- DictionaryValue original_dict;
- Value* null_weak = original_dict.Set("null", std::make_unique<Value>());
- Value* bool_weak = original_dict.Set("bool", std::make_unique<Value>(true));
- Value* int_weak = original_dict.Set("int", std::make_unique<Value>(42));
- Value* double_weak =
- original_dict.Set("double", std::make_unique<Value>(3.14));
- Value* string_weak =
- original_dict.Set("string", std::make_unique<Value>("hello"));
- Value* string16_weak = original_dict.Set(
- "string16", std::make_unique<Value>(ASCIIToUTF16("hello16")));
-
- Value* binary_weak = original_dict.Set(
- "binary", std::make_unique<Value>(Value::BlobStorage(42, '!')));
-
- Value::ListStorage storage;
- storage.emplace_back(0);
- storage.emplace_back(1);
- Value* list_weak =
- original_dict.Set("list", std::make_unique<Value>(std::move(storage)));
- Value* list_element_0_weak = &list_weak->GetList()[0];
- Value* list_element_1_weak = &list_weak->GetList()[1];
-
- DictionaryValue* dict_weak = original_dict.SetDictionary(
- "dictionary", std::make_unique<DictionaryValue>());
- dict_weak->SetString("key", "value");
-
- auto copy_dict = original_dict.CreateDeepCopy();
- ASSERT_TRUE(copy_dict.get());
- ASSERT_NE(copy_dict.get(), &original_dict);
-
- Value* copy_null = nullptr;
- ASSERT_TRUE(copy_dict->Get("null", ©_null));
- ASSERT_TRUE(copy_null);
- ASSERT_NE(copy_null, null_weak);
- ASSERT_TRUE(copy_null->is_none());
-
- Value* copy_bool = nullptr;
- ASSERT_TRUE(copy_dict->Get("bool", ©_bool));
- ASSERT_TRUE(copy_bool);
- ASSERT_NE(copy_bool, bool_weak);
- ASSERT_TRUE(copy_bool->is_bool());
- bool copy_bool_value = false;
- ASSERT_TRUE(copy_bool->GetAsBoolean(©_bool_value));
- ASSERT_TRUE(copy_bool_value);
-
- Value* copy_int = nullptr;
- ASSERT_TRUE(copy_dict->Get("int", ©_int));
- ASSERT_TRUE(copy_int);
- ASSERT_NE(copy_int, int_weak);
- ASSERT_TRUE(copy_int->is_int());
- int copy_int_value = 0;
- ASSERT_TRUE(copy_int->GetAsInteger(©_int_value));
- ASSERT_EQ(42, copy_int_value);
-
- Value* copy_double = nullptr;
- ASSERT_TRUE(copy_dict->Get("double", ©_double));
- ASSERT_TRUE(copy_double);
- ASSERT_NE(copy_double, double_weak);
- ASSERT_TRUE(copy_double->is_double());
- double copy_double_value = 0;
- ASSERT_TRUE(copy_double->GetAsDouble(©_double_value));
- ASSERT_EQ(3.14, copy_double_value);
-
- Value* copy_string = nullptr;
- ASSERT_TRUE(copy_dict->Get("string", ©_string));
- ASSERT_TRUE(copy_string);
- ASSERT_NE(copy_string, string_weak);
- ASSERT_TRUE(copy_string->is_string());
- std::string copy_string_value;
- string16 copy_string16_value;
- ASSERT_TRUE(copy_string->GetAsString(©_string_value));
- ASSERT_TRUE(copy_string->GetAsString(©_string16_value));
- ASSERT_EQ(std::string("hello"), copy_string_value);
- ASSERT_EQ(ASCIIToUTF16("hello"), copy_string16_value);
-
- Value* copy_string16 = nullptr;
- ASSERT_TRUE(copy_dict->Get("string16", ©_string16));
- ASSERT_TRUE(copy_string16);
- ASSERT_NE(copy_string16, string16_weak);
- ASSERT_TRUE(copy_string16->is_string());
- ASSERT_TRUE(copy_string16->GetAsString(©_string_value));
- ASSERT_TRUE(copy_string16->GetAsString(©_string16_value));
- ASSERT_EQ(std::string("hello16"), copy_string_value);
- ASSERT_EQ(ASCIIToUTF16("hello16"), copy_string16_value);
-
- Value* copy_binary = nullptr;
- ASSERT_TRUE(copy_dict->Get("binary", ©_binary));
- ASSERT_TRUE(copy_binary);
- ASSERT_NE(copy_binary, binary_weak);
- ASSERT_TRUE(copy_binary->is_blob());
- ASSERT_NE(binary_weak->GetBlob().data(), copy_binary->GetBlob().data());
- ASSERT_EQ(binary_weak->GetBlob(), copy_binary->GetBlob());
-
- Value* copy_value = nullptr;
- ASSERT_TRUE(copy_dict->Get("list", ©_value));
- ASSERT_TRUE(copy_value);
- ASSERT_NE(copy_value, list_weak);
- ASSERT_TRUE(copy_value->is_list());
- ListValue* copy_list = nullptr;
- ASSERT_TRUE(copy_value->GetAsList(©_list));
- ASSERT_TRUE(copy_list);
- ASSERT_EQ(2U, copy_list->GetSize());
-
- Value* copy_list_element_0;
- ASSERT_TRUE(copy_list->Get(0, ©_list_element_0));
- ASSERT_TRUE(copy_list_element_0);
- ASSERT_NE(copy_list_element_0, list_element_0_weak);
- int copy_list_element_0_value;
- ASSERT_TRUE(copy_list_element_0->GetAsInteger(©_list_element_0_value));
- ASSERT_EQ(0, copy_list_element_0_value);
-
- Value* copy_list_element_1;
- ASSERT_TRUE(copy_list->Get(1, ©_list_element_1));
- ASSERT_TRUE(copy_list_element_1);
- ASSERT_NE(copy_list_element_1, list_element_1_weak);
- int copy_list_element_1_value;
- ASSERT_TRUE(copy_list_element_1->GetAsInteger(©_list_element_1_value));
- ASSERT_EQ(1, copy_list_element_1_value);
-
- copy_value = nullptr;
- ASSERT_TRUE(copy_dict->Get("dictionary", ©_value));
- ASSERT_TRUE(copy_value);
- ASSERT_NE(copy_value, dict_weak);
- ASSERT_TRUE(copy_value->is_dict());
- DictionaryValue* copy_nested_dictionary = nullptr;
- ASSERT_TRUE(copy_value->GetAsDictionary(©_nested_dictionary));
- ASSERT_TRUE(copy_nested_dictionary);
- EXPECT_TRUE(copy_nested_dictionary->HasKey("key"));
-}
-
-TEST(ValuesTest, Equals) {
- auto null1 = std::make_unique<Value>();
- auto null2 = std::make_unique<Value>();
- EXPECT_NE(null1.get(), null2.get());
- EXPECT_EQ(*null1, *null2);
-
- Value boolean(false);
- EXPECT_NE(*null1, boolean);
-
- DictionaryValue dv;
- dv.SetBoolean("a", false);
- dv.SetInteger("b", 2);
- dv.SetDouble("c", 2.5);
- dv.SetString("d1", "string");
- dv.SetString("d2", ASCIIToUTF16("http://google.com"));
- dv.Set("e", std::make_unique<Value>());
-
- auto copy = dv.CreateDeepCopy();
- EXPECT_EQ(dv, *copy);
-
- std::unique_ptr<ListValue> list(new ListValue);
- list->Append(std::make_unique<Value>());
- list->Append(WrapUnique(new DictionaryValue));
- auto list_copy = std::make_unique<Value>(list->Clone());
-
- ListValue* list_weak = dv.SetList("f", std::move(list));
- EXPECT_NE(dv, *copy);
- copy->Set("f", std::move(list_copy));
- EXPECT_EQ(dv, *copy);
-
- list_weak->Append(std::make_unique<Value>(true));
- EXPECT_NE(dv, *copy);
-
- // Check if Equals detects differences in only the keys.
- copy = dv.CreateDeepCopy();
- EXPECT_EQ(dv, *copy);
- copy->Remove("a", nullptr);
- copy->SetBoolean("aa", false);
- EXPECT_NE(dv, *copy);
-}
-
-TEST(ValuesTest, Comparisons) {
- // Test None Values.
- Value null1;
- Value null2;
- EXPECT_EQ(null1, null2);
- EXPECT_FALSE(null1 != null2);
- EXPECT_FALSE(null1 < null2);
- EXPECT_FALSE(null1 > null2);
- EXPECT_LE(null1, null2);
- EXPECT_GE(null1, null2);
-
- // Test Bool Values.
- Value bool1(false);
- Value bool2(true);
- EXPECT_FALSE(bool1 == bool2);
- EXPECT_NE(bool1, bool2);
- EXPECT_LT(bool1, bool2);
- EXPECT_FALSE(bool1 > bool2);
- EXPECT_LE(bool1, bool2);
- EXPECT_FALSE(bool1 >= bool2);
-
- // Test Int Values.
- Value int1(1);
- Value int2(2);
- EXPECT_FALSE(int1 == int2);
- EXPECT_NE(int1, int2);
- EXPECT_LT(int1, int2);
- EXPECT_FALSE(int1 > int2);
- EXPECT_LE(int1, int2);
- EXPECT_FALSE(int1 >= int2);
-
- // Test Double Values.
- Value double1(1.0);
- Value double2(2.0);
- EXPECT_FALSE(double1 == double2);
- EXPECT_NE(double1, double2);
- EXPECT_LT(double1, double2);
- EXPECT_FALSE(double1 > double2);
- EXPECT_LE(double1, double2);
- EXPECT_FALSE(double1 >= double2);
-
- // Test String Values.
- Value string1("1");
- Value string2("2");
- EXPECT_FALSE(string1 == string2);
- EXPECT_NE(string1, string2);
- EXPECT_LT(string1, string2);
- EXPECT_FALSE(string1 > string2);
- EXPECT_LE(string1, string2);
- EXPECT_FALSE(string1 >= string2);
-
- // Test Binary Values.
- Value binary1(Value::BlobStorage{0x01});
- Value binary2(Value::BlobStorage{0x02});
- EXPECT_FALSE(binary1 == binary2);
- EXPECT_NE(binary1, binary2);
- EXPECT_LT(binary1, binary2);
- EXPECT_FALSE(binary1 > binary2);
- EXPECT_LE(binary1, binary2);
- EXPECT_FALSE(binary1 >= binary2);
-
- // Test Empty List Values.
- ListValue null_list1;
- ListValue null_list2;
- EXPECT_EQ(null_list1, null_list2);
- EXPECT_FALSE(null_list1 != null_list2);
- EXPECT_FALSE(null_list1 < null_list2);
- EXPECT_FALSE(null_list1 > null_list2);
- EXPECT_LE(null_list1, null_list2);
- EXPECT_GE(null_list1, null_list2);
-
- // Test Non Empty List Values.
- ListValue int_list1;
- ListValue int_list2;
- int_list1.AppendInteger(1);
- int_list2.AppendInteger(2);
- EXPECT_FALSE(int_list1 == int_list2);
- EXPECT_NE(int_list1, int_list2);
- EXPECT_LT(int_list1, int_list2);
- EXPECT_FALSE(int_list1 > int_list2);
- EXPECT_LE(int_list1, int_list2);
- EXPECT_FALSE(int_list1 >= int_list2);
-
- // Test Empty Dict Values.
- DictionaryValue null_dict1;
- DictionaryValue null_dict2;
- EXPECT_EQ(null_dict1, null_dict2);
- EXPECT_FALSE(null_dict1 != null_dict2);
- EXPECT_FALSE(null_dict1 < null_dict2);
- EXPECT_FALSE(null_dict1 > null_dict2);
- EXPECT_LE(null_dict1, null_dict2);
- EXPECT_GE(null_dict1, null_dict2);
-
- // Test Non Empty Dict Values.
- DictionaryValue int_dict1;
- DictionaryValue int_dict2;
- int_dict1.SetInteger("key", 1);
- int_dict2.SetInteger("key", 2);
- EXPECT_FALSE(int_dict1 == int_dict2);
- EXPECT_NE(int_dict1, int_dict2);
- EXPECT_LT(int_dict1, int_dict2);
- EXPECT_FALSE(int_dict1 > int_dict2);
- EXPECT_LE(int_dict1, int_dict2);
- EXPECT_FALSE(int_dict1 >= int_dict2);
-
- // Test Values of different types.
- std::vector<Value> values;
- values.emplace_back(std::move(null1));
- values.emplace_back(std::move(bool1));
- values.emplace_back(std::move(int1));
- values.emplace_back(std::move(double1));
- values.emplace_back(std::move(string1));
- values.emplace_back(std::move(binary1));
- values.emplace_back(std::move(int_dict1));
- values.emplace_back(std::move(int_list1));
- for (size_t i = 0; i < values.size(); ++i) {
- for (size_t j = i + 1; j < values.size(); ++j) {
- EXPECT_FALSE(values[i] == values[j]);
- EXPECT_NE(values[i], values[j]);
- EXPECT_LT(values[i], values[j]);
- EXPECT_FALSE(values[i] > values[j]);
- EXPECT_LE(values[i], values[j]);
- EXPECT_FALSE(values[i] >= values[j]);
- }
- }
-}
-
-TEST(ValuesTest, DeepCopyCovariantReturnTypes) {
- DictionaryValue original_dict;
- Value* null_weak = original_dict.SetKey("null", Value());
- Value* bool_weak = original_dict.SetKey("bool", Value(true));
- Value* int_weak = original_dict.SetKey("int", Value(42));
- Value* double_weak = original_dict.SetKey("double", Value(3.14));
- Value* string_weak = original_dict.SetKey("string", Value("hello"));
- Value* string16_weak =
- original_dict.SetKey("string16", Value(ASCIIToUTF16("hello16")));
- Value* binary_weak =
- original_dict.SetKey("binary", Value(Value::BlobStorage(42, '!')));
-
- Value::ListStorage storage;
- storage.emplace_back(0);
- storage.emplace_back(1);
- Value* list_weak = original_dict.SetKey("list", Value(std::move(storage)));
-
- auto copy_dict = std::make_unique<Value>(original_dict.Clone());
- auto copy_null = std::make_unique<Value>(null_weak->Clone());
- auto copy_bool = std::make_unique<Value>(bool_weak->Clone());
- auto copy_int = std::make_unique<Value>(int_weak->Clone());
- auto copy_double = std::make_unique<Value>(double_weak->Clone());
- auto copy_string = std::make_unique<Value>(string_weak->Clone());
- auto copy_string16 = std::make_unique<Value>(string16_weak->Clone());
- auto copy_binary = std::make_unique<Value>(binary_weak->Clone());
- auto copy_list = std::make_unique<Value>(list_weak->Clone());
-
- EXPECT_EQ(original_dict, *copy_dict);
- EXPECT_EQ(*null_weak, *copy_null);
- EXPECT_EQ(*bool_weak, *copy_bool);
- EXPECT_EQ(*int_weak, *copy_int);
- EXPECT_EQ(*double_weak, *copy_double);
- EXPECT_EQ(*string_weak, *copy_string);
- EXPECT_EQ(*string16_weak, *copy_string16);
- EXPECT_EQ(*binary_weak, *copy_binary);
- EXPECT_EQ(*list_weak, *copy_list);
-}
-
-TEST(ValuesTest, RemoveEmptyChildren) {
- auto root = std::make_unique<DictionaryValue>();
- // Remove empty lists and dictionaries.
- root->Set("empty_dict", std::make_unique<DictionaryValue>());
- root->Set("empty_list", std::make_unique<ListValue>());
- root->SetWithoutPathExpansion("a.b.c.d.e",
- std::make_unique<DictionaryValue>());
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_TRUE(root->empty());
-
- // Make sure we don't prune too much.
- root->SetBoolean("bool", true);
- root->Set("empty_dict", std::make_unique<DictionaryValue>());
- root->SetString("empty_string", std::string());
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(2U, root->size());
-
- // Should do nothing.
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(2U, root->size());
-
- // Nested test cases. These should all reduce back to the bool and string
- // set above.
- {
- root->Set("a.b.c.d.e", std::make_unique<DictionaryValue>());
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(2U, root->size());
- }
- {
- auto inner = std::make_unique<DictionaryValue>();
- inner->Set("empty_dict", std::make_unique<DictionaryValue>());
- inner->Set("empty_list", std::make_unique<ListValue>());
- root->Set("dict_with_empty_children", std::move(inner));
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(2U, root->size());
- }
- {
- auto inner = std::make_unique<ListValue>();
- inner->Append(std::make_unique<DictionaryValue>());
- inner->Append(std::make_unique<ListValue>());
- root->Set("list_with_empty_children", std::move(inner));
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(2U, root->size());
- }
-
- // Nested with siblings.
- {
- auto inner = std::make_unique<ListValue>();
- inner->Append(std::make_unique<DictionaryValue>());
- inner->Append(std::make_unique<ListValue>());
- root->Set("list_with_empty_children", std::move(inner));
- auto inner2 = std::make_unique<DictionaryValue>();
- inner2->Set("empty_dict", std::make_unique<DictionaryValue>());
- inner2->Set("empty_list", std::make_unique<ListValue>());
- root->Set("dict_with_empty_children", std::move(inner2));
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(2U, root->size());
- }
-
- // Make sure nested values don't get pruned.
- {
- auto inner = std::make_unique<ListValue>();
- auto inner2 = std::make_unique<ListValue>();
- inner2->Append(std::make_unique<Value>("hello"));
- inner->Append(std::make_unique<DictionaryValue>());
- inner->Append(std::move(inner2));
- root->Set("list_with_empty_children", std::move(inner));
- root = root->DeepCopyWithoutEmptyChildren();
- EXPECT_EQ(3U, root->size());
-
- ListValue* inner_value, *inner_value2;
- EXPECT_TRUE(root->GetList("list_with_empty_children", &inner_value));
- EXPECT_EQ(1U, inner_value->GetSize()); // Dictionary was pruned.
- EXPECT_TRUE(inner_value->GetList(0, &inner_value2));
- EXPECT_EQ(1U, inner_value2->GetSize());
- }
-}
-
-TEST(ValuesTest, MergeDictionary) {
- std::unique_ptr<DictionaryValue> base(new DictionaryValue);
- base->SetString("base_key", "base_key_value_base");
- base->SetString("collide_key", "collide_key_value_base");
- std::unique_ptr<DictionaryValue> base_sub_dict(new DictionaryValue);
- base_sub_dict->SetString("sub_base_key", "sub_base_key_value_base");
- base_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_base");
- base->Set("sub_dict_key", std::move(base_sub_dict));
-
- std::unique_ptr<DictionaryValue> merge(new DictionaryValue);
- merge->SetString("merge_key", "merge_key_value_merge");
- merge->SetString("collide_key", "collide_key_value_merge");
- std::unique_ptr<DictionaryValue> merge_sub_dict(new DictionaryValue);
- merge_sub_dict->SetString("sub_merge_key", "sub_merge_key_value_merge");
- merge_sub_dict->SetString("sub_collide_key", "sub_collide_key_value_merge");
- merge->Set("sub_dict_key", std::move(merge_sub_dict));
-
- base->MergeDictionary(merge.get());
-
- EXPECT_EQ(4U, base->size());
- std::string base_key_value;
- EXPECT_TRUE(base->GetString("base_key", &base_key_value));
- EXPECT_EQ("base_key_value_base", base_key_value); // Base value preserved.
- std::string collide_key_value;
- EXPECT_TRUE(base->GetString("collide_key", &collide_key_value));
- EXPECT_EQ("collide_key_value_merge", collide_key_value); // Replaced.
- std::string merge_key_value;
- EXPECT_TRUE(base->GetString("merge_key", &merge_key_value));
- EXPECT_EQ("merge_key_value_merge", merge_key_value); // Merged in.
-
- DictionaryValue* res_sub_dict;
- EXPECT_TRUE(base->GetDictionary("sub_dict_key", &res_sub_dict));
- EXPECT_EQ(3U, res_sub_dict->size());
- std::string sub_base_key_value;
- EXPECT_TRUE(res_sub_dict->GetString("sub_base_key", &sub_base_key_value));
- EXPECT_EQ("sub_base_key_value_base", sub_base_key_value); // Preserved.
- std::string sub_collide_key_value;
- EXPECT_TRUE(res_sub_dict->GetString("sub_collide_key",
- &sub_collide_key_value));
- EXPECT_EQ("sub_collide_key_value_merge", sub_collide_key_value); // Replaced.
- std::string sub_merge_key_value;
- EXPECT_TRUE(res_sub_dict->GetString("sub_merge_key", &sub_merge_key_value));
- EXPECT_EQ("sub_merge_key_value_merge", sub_merge_key_value); // Merged in.
-}
-
-TEST(ValuesTest, MergeDictionaryDeepCopy) {
- std::unique_ptr<DictionaryValue> child(new DictionaryValue);
- DictionaryValue* original_child = child.get();
- child->SetString("test", "value");
- EXPECT_EQ(1U, child->size());
-
- std::string value;
- EXPECT_TRUE(child->GetString("test", &value));
- EXPECT_EQ("value", value);
-
- std::unique_ptr<DictionaryValue> base(new DictionaryValue);
- base->Set("dict", std::move(child));
- EXPECT_EQ(1U, base->size());
-
- DictionaryValue* ptr;
- EXPECT_TRUE(base->GetDictionary("dict", &ptr));
- EXPECT_EQ(original_child, ptr);
-
- std::unique_ptr<DictionaryValue> merged(new DictionaryValue);
- merged->MergeDictionary(base.get());
- EXPECT_EQ(1U, merged->size());
- EXPECT_TRUE(merged->GetDictionary("dict", &ptr));
- EXPECT_NE(original_child, ptr);
- EXPECT_TRUE(ptr->GetString("test", &value));
- EXPECT_EQ("value", value);
-
- original_child->SetString("test", "overwrite");
- base.reset();
- EXPECT_TRUE(ptr->GetString("test", &value));
- EXPECT_EQ("value", value);
-}
-
-TEST(ValuesTest, DictionaryIterator) {
- DictionaryValue dict;
- for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
- ADD_FAILURE();
- }
-
- Value value1("value1");
- dict.SetKey("key1", value1.Clone());
- bool seen1 = false;
- for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
- EXPECT_FALSE(seen1);
- EXPECT_EQ("key1", it.key());
- EXPECT_EQ(value1, it.value());
- seen1 = true;
- }
- EXPECT_TRUE(seen1);
-
- Value value2("value2");
- dict.SetKey("key2", value2.Clone());
- bool seen2 = seen1 = false;
- for (DictionaryValue::Iterator it(dict); !it.IsAtEnd(); it.Advance()) {
- if (it.key() == "key1") {
- EXPECT_FALSE(seen1);
- EXPECT_EQ(value1, it.value());
- seen1 = true;
- } else if (it.key() == "key2") {
- EXPECT_FALSE(seen2);
- EXPECT_EQ(value2, it.value());
- seen2 = true;
- } else {
- ADD_FAILURE();
- }
- }
- EXPECT_TRUE(seen1);
- EXPECT_TRUE(seen2);
-}
-
-TEST(ValuesTest, StdDictionaryIterator) {
- DictionaryValue dict;
- for (auto it = dict.begin(); it != dict.end(); ++it) {
- ADD_FAILURE();
- }
-
- Value value1("value1");
- dict.SetKey("key1", value1.Clone());
- bool seen1 = false;
- for (const auto& it : dict) {
- EXPECT_FALSE(seen1);
- EXPECT_EQ("key1", it.first);
- EXPECT_EQ(value1, *it.second);
- seen1 = true;
- }
- EXPECT_TRUE(seen1);
-
- Value value2("value2");
- dict.SetKey("key2", value2.Clone());
- bool seen2 = seen1 = false;
- for (const auto& it : dict) {
- if (it.first == "key1") {
- EXPECT_FALSE(seen1);
- EXPECT_EQ(value1, *it.second);
- seen1 = true;
- } else if (it.first == "key2") {
- EXPECT_FALSE(seen2);
- EXPECT_EQ(value2, *it.second);
- seen2 = true;
- } else {
- ADD_FAILURE();
- }
- }
- EXPECT_TRUE(seen1);
- EXPECT_TRUE(seen2);
-}
-
-// DictionaryValue/ListValue's Get*() methods should accept NULL as an out-value
-// and still return true/false based on success.
-TEST(ValuesTest, GetWithNullOutValue) {
- DictionaryValue main_dict;
- ListValue main_list;
-
- Value bool_value(false);
- Value int_value(1234);
- Value double_value(12.34567);
- Value string_value("foo");
- Value binary_value(Value::Type::BINARY);
- DictionaryValue dict_value;
- ListValue list_value;
-
- main_dict.SetKey("bool", bool_value.Clone());
- main_dict.SetKey("int", int_value.Clone());
- main_dict.SetKey("double", double_value.Clone());
- main_dict.SetKey("string", string_value.Clone());
- main_dict.SetKey("binary", binary_value.Clone());
- main_dict.SetKey("dict", dict_value.Clone());
- main_dict.SetKey("list", list_value.Clone());
-
- main_list.Append(std::make_unique<Value>(bool_value.Clone()));
- main_list.Append(std::make_unique<Value>(int_value.Clone()));
- main_list.Append(std::make_unique<Value>(double_value.Clone()));
- main_list.Append(std::make_unique<Value>(string_value.Clone()));
- main_list.Append(std::make_unique<Value>(binary_value.Clone()));
- main_list.Append(std::make_unique<Value>(dict_value.Clone()));
- main_list.Append(std::make_unique<Value>(list_value.Clone()));
-
- EXPECT_TRUE(main_dict.Get("bool", nullptr));
- EXPECT_TRUE(main_dict.Get("int", nullptr));
- EXPECT_TRUE(main_dict.Get("double", nullptr));
- EXPECT_TRUE(main_dict.Get("string", nullptr));
- EXPECT_TRUE(main_dict.Get("binary", nullptr));
- EXPECT_TRUE(main_dict.Get("dict", nullptr));
- EXPECT_TRUE(main_dict.Get("list", nullptr));
- EXPECT_FALSE(main_dict.Get("DNE", nullptr));
-
- EXPECT_TRUE(main_dict.GetBoolean("bool", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("int", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("double", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("string", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("binary", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("dict", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("list", nullptr));
- EXPECT_FALSE(main_dict.GetBoolean("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetInteger("bool", nullptr));
- EXPECT_TRUE(main_dict.GetInteger("int", nullptr));
- EXPECT_FALSE(main_dict.GetInteger("double", nullptr));
- EXPECT_FALSE(main_dict.GetInteger("string", nullptr));
- EXPECT_FALSE(main_dict.GetInteger("binary", nullptr));
- EXPECT_FALSE(main_dict.GetInteger("dict", nullptr));
- EXPECT_FALSE(main_dict.GetInteger("list", nullptr));
- EXPECT_FALSE(main_dict.GetInteger("DNE", nullptr));
-
- // Both int and double values can be obtained from GetDouble.
- EXPECT_FALSE(main_dict.GetDouble("bool", nullptr));
- EXPECT_TRUE(main_dict.GetDouble("int", nullptr));
- EXPECT_TRUE(main_dict.GetDouble("double", nullptr));
- EXPECT_FALSE(main_dict.GetDouble("string", nullptr));
- EXPECT_FALSE(main_dict.GetDouble("binary", nullptr));
- EXPECT_FALSE(main_dict.GetDouble("dict", nullptr));
- EXPECT_FALSE(main_dict.GetDouble("list", nullptr));
- EXPECT_FALSE(main_dict.GetDouble("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetString("bool", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("int", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(
- main_dict.GetString("double", static_cast<std::string*>(nullptr)));
- EXPECT_TRUE(
- main_dict.GetString("string", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(
- main_dict.GetString("binary", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("dict", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("list", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("DNE", static_cast<std::string*>(nullptr)));
-
- EXPECT_FALSE(main_dict.GetString("bool", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("int", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("double", static_cast<string16*>(nullptr)));
- EXPECT_TRUE(main_dict.GetString("string", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("binary", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("dict", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("list", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetString("DNE", static_cast<string16*>(nullptr)));
-
- EXPECT_FALSE(main_dict.GetBinary("bool", nullptr));
- EXPECT_FALSE(main_dict.GetBinary("int", nullptr));
- EXPECT_FALSE(main_dict.GetBinary("double", nullptr));
- EXPECT_FALSE(main_dict.GetBinary("string", nullptr));
- EXPECT_TRUE(main_dict.GetBinary("binary", nullptr));
- EXPECT_FALSE(main_dict.GetBinary("dict", nullptr));
- EXPECT_FALSE(main_dict.GetBinary("list", nullptr));
- EXPECT_FALSE(main_dict.GetBinary("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetDictionary("bool", nullptr));
- EXPECT_FALSE(main_dict.GetDictionary("int", nullptr));
- EXPECT_FALSE(main_dict.GetDictionary("double", nullptr));
- EXPECT_FALSE(main_dict.GetDictionary("string", nullptr));
- EXPECT_FALSE(main_dict.GetDictionary("binary", nullptr));
- EXPECT_TRUE(main_dict.GetDictionary("dict", nullptr));
- EXPECT_FALSE(main_dict.GetDictionary("list", nullptr));
- EXPECT_FALSE(main_dict.GetDictionary("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetList("bool", nullptr));
- EXPECT_FALSE(main_dict.GetList("int", nullptr));
- EXPECT_FALSE(main_dict.GetList("double", nullptr));
- EXPECT_FALSE(main_dict.GetList("string", nullptr));
- EXPECT_FALSE(main_dict.GetList("binary", nullptr));
- EXPECT_FALSE(main_dict.GetList("dict", nullptr));
- EXPECT_TRUE(main_dict.GetList("list", nullptr));
- EXPECT_FALSE(main_dict.GetList("DNE", nullptr));
-
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("bool", nullptr));
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("int", nullptr));
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("double", nullptr));
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("string", nullptr));
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("binary", nullptr));
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("dict", nullptr));
- EXPECT_TRUE(main_dict.GetWithoutPathExpansion("list", nullptr));
- EXPECT_FALSE(main_dict.GetWithoutPathExpansion("DNE", nullptr));
-
- EXPECT_TRUE(main_dict.GetBooleanWithoutPathExpansion("bool", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("int", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("double", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("string", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("binary", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("dict", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("list", nullptr));
- EXPECT_FALSE(main_dict.GetBooleanWithoutPathExpansion("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("bool", nullptr));
- EXPECT_TRUE(main_dict.GetIntegerWithoutPathExpansion("int", nullptr));
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("double", nullptr));
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("string", nullptr));
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("binary", nullptr));
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("dict", nullptr));
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("list", nullptr));
- EXPECT_FALSE(main_dict.GetIntegerWithoutPathExpansion("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetDoubleWithoutPathExpansion("bool", nullptr));
- EXPECT_TRUE(main_dict.GetDoubleWithoutPathExpansion("int", nullptr));
- EXPECT_TRUE(main_dict.GetDoubleWithoutPathExpansion("double", nullptr));
- EXPECT_FALSE(main_dict.GetDoubleWithoutPathExpansion("string", nullptr));
- EXPECT_FALSE(main_dict.GetDoubleWithoutPathExpansion("binary", nullptr));
- EXPECT_FALSE(main_dict.GetDoubleWithoutPathExpansion("dict", nullptr));
- EXPECT_FALSE(main_dict.GetDoubleWithoutPathExpansion("list", nullptr));
- EXPECT_FALSE(main_dict.GetDoubleWithoutPathExpansion("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "bool", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "int", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "double", static_cast<std::string*>(nullptr)));
- EXPECT_TRUE(main_dict.GetStringWithoutPathExpansion(
- "string", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "binary", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "dict", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "list", static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "DNE", static_cast<std::string*>(nullptr)));
-
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "bool", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "int", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "double", static_cast<string16*>(nullptr)));
- EXPECT_TRUE(main_dict.GetStringWithoutPathExpansion(
- "string", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "binary", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "dict", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "list", static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_dict.GetStringWithoutPathExpansion(
- "DNE", static_cast<string16*>(nullptr)));
-
- // There is no GetBinaryWithoutPathExpansion for some reason, but if there
- // were it should be tested here...
-
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("bool", nullptr));
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("int", nullptr));
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("double", nullptr));
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("string", nullptr));
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("binary", nullptr));
- EXPECT_TRUE(main_dict.GetDictionaryWithoutPathExpansion("dict", nullptr));
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("list", nullptr));
- EXPECT_FALSE(main_dict.GetDictionaryWithoutPathExpansion("DNE", nullptr));
-
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("bool", nullptr));
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("int", nullptr));
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("double", nullptr));
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("string", nullptr));
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("binary", nullptr));
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("dict", nullptr));
- EXPECT_TRUE(main_dict.GetListWithoutPathExpansion("list", nullptr));
- EXPECT_FALSE(main_dict.GetListWithoutPathExpansion("DNE", nullptr));
-
- EXPECT_TRUE(main_list.Get(0, nullptr));
- EXPECT_TRUE(main_list.Get(1, nullptr));
- EXPECT_TRUE(main_list.Get(2, nullptr));
- EXPECT_TRUE(main_list.Get(3, nullptr));
- EXPECT_TRUE(main_list.Get(4, nullptr));
- EXPECT_TRUE(main_list.Get(5, nullptr));
- EXPECT_TRUE(main_list.Get(6, nullptr));
- EXPECT_FALSE(main_list.Get(7, nullptr));
-
- EXPECT_TRUE(main_list.GetBoolean(0, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(1, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(2, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(3, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(4, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(5, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(6, nullptr));
- EXPECT_FALSE(main_list.GetBoolean(7, nullptr));
-
- EXPECT_FALSE(main_list.GetInteger(0, nullptr));
- EXPECT_TRUE(main_list.GetInteger(1, nullptr));
- EXPECT_FALSE(main_list.GetInteger(2, nullptr));
- EXPECT_FALSE(main_list.GetInteger(3, nullptr));
- EXPECT_FALSE(main_list.GetInteger(4, nullptr));
- EXPECT_FALSE(main_list.GetInteger(5, nullptr));
- EXPECT_FALSE(main_list.GetInteger(6, nullptr));
- EXPECT_FALSE(main_list.GetInteger(7, nullptr));
-
- EXPECT_FALSE(main_list.GetDouble(0, nullptr));
- EXPECT_TRUE(main_list.GetDouble(1, nullptr));
- EXPECT_TRUE(main_list.GetDouble(2, nullptr));
- EXPECT_FALSE(main_list.GetDouble(3, nullptr));
- EXPECT_FALSE(main_list.GetDouble(4, nullptr));
- EXPECT_FALSE(main_list.GetDouble(5, nullptr));
- EXPECT_FALSE(main_list.GetDouble(6, nullptr));
- EXPECT_FALSE(main_list.GetDouble(7, nullptr));
-
- EXPECT_FALSE(main_list.GetString(0, static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(1, static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(2, static_cast<std::string*>(nullptr)));
- EXPECT_TRUE(main_list.GetString(3, static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(4, static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(5, static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(6, static_cast<std::string*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(7, static_cast<std::string*>(nullptr)));
-
- EXPECT_FALSE(main_list.GetString(0, static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(1, static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(2, static_cast<string16*>(nullptr)));
- EXPECT_TRUE(main_list.GetString(3, static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(4, static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(5, static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(6, static_cast<string16*>(nullptr)));
- EXPECT_FALSE(main_list.GetString(7, static_cast<string16*>(nullptr)));
-
- EXPECT_FALSE(main_list.GetDictionary(0, nullptr));
- EXPECT_FALSE(main_list.GetDictionary(1, nullptr));
- EXPECT_FALSE(main_list.GetDictionary(2, nullptr));
- EXPECT_FALSE(main_list.GetDictionary(3, nullptr));
- EXPECT_FALSE(main_list.GetDictionary(4, nullptr));
- EXPECT_TRUE(main_list.GetDictionary(5, nullptr));
- EXPECT_FALSE(main_list.GetDictionary(6, nullptr));
- EXPECT_FALSE(main_list.GetDictionary(7, nullptr));
-
- EXPECT_FALSE(main_list.GetList(0, nullptr));
- EXPECT_FALSE(main_list.GetList(1, nullptr));
- EXPECT_FALSE(main_list.GetList(2, nullptr));
- EXPECT_FALSE(main_list.GetList(3, nullptr));
- EXPECT_FALSE(main_list.GetList(4, nullptr));
- EXPECT_FALSE(main_list.GetList(5, nullptr));
- EXPECT_TRUE(main_list.GetList(6, nullptr));
- EXPECT_FALSE(main_list.GetList(7, nullptr));
-}
-
-TEST(ValuesTest, SelfSwap) {
- base::Value test(1);
- std::swap(test, test);
- EXPECT_EQ(1, test.GetInt());
-}
-
-TEST(ValuesTest, FromToUniquePtrValue) {
- std::unique_ptr<DictionaryValue> dict = std::make_unique<DictionaryValue>();
- dict->SetString("name", "Froogle");
- dict->SetString("url", "http://froogle.com");
- Value dict_copy = dict->Clone();
-
- Value dict_converted = Value::FromUniquePtrValue(std::move(dict));
- EXPECT_EQ(dict_copy, dict_converted);
-
- std::unique_ptr<Value> val =
- Value::ToUniquePtrValue(std::move(dict_converted));
- EXPECT_EQ(dict_copy, *val);
-}
-
-} // namespace base
diff --git a/base/version_unittest.cc b/base/version_unittest.cc
deleted file mode 100644
index 285ca9c..0000000
--- a/base/version_unittest.cc
+++ /dev/null
@@ -1,200 +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/version.h"
-
-#include <stddef.h>
-#include <stdint.h>
-#include <utility>
-
-#include "base/macros.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-TEST(VersionTest, DefaultConstructor) {
- base::Version v;
- EXPECT_FALSE(v.IsValid());
-}
-
-TEST(VersionTest, ValueSemantics) {
- base::Version v1("1.2.3.4");
- EXPECT_TRUE(v1.IsValid());
- base::Version v3;
- EXPECT_FALSE(v3.IsValid());
- {
- base::Version v2(v1);
- v3 = v2;
- EXPECT_TRUE(v2.IsValid());
- EXPECT_EQ(v1, v2);
- }
- EXPECT_EQ(v3, v1);
-}
-
-TEST(VersionTest, MoveSemantics) {
- const std::vector<uint32_t> components = {1, 2, 3, 4};
- base::Version v1(std::move(components));
- EXPECT_TRUE(v1.IsValid());
- base::Version v2("1.2.3.4");
- EXPECT_EQ(v1, v2);
-}
-
-TEST(VersionTest, GetVersionFromString) {
- static const struct version_string {
- const char* input;
- size_t parts;
- uint32_t firstpart;
- bool success;
- } cases[] = {
- {"", 0, 0, false},
- {" ", 0, 0, false},
- {"\t", 0, 0, false},
- {"\n", 0, 0, false},
- {" ", 0, 0, false},
- {".", 0, 0, false},
- {" . ", 0, 0, false},
- {"0", 1, 0, true},
- {"0.", 0, 0, false},
- {"0.0", 2, 0, true},
- {"4294967295.0", 2, 4294967295, true},
- {"4294967296.0", 0, 0, false},
- {"-1.0", 0, 0, false},
- {"1.-1.0", 0, 0, false},
- {"1,--1.0", 0, 0, false},
- {"+1.0", 0, 0, false},
- {"1.+1.0", 0, 0, false},
- {"1+1.0", 0, 0, false},
- {"++1.0", 0, 0, false},
- {"1.0a", 0, 0, false},
- {"1.2.3.4.5.6.7.8.9.0", 10, 1, true},
- {"02.1", 0, 0, false},
- {"0.01", 2, 0, true},
- {"f.1", 0, 0, false},
- {"15.007.20011", 3, 15, true},
- {"15.5.28.130162", 4, 15, true},
- };
-
- for (size_t i = 0; i < arraysize(cases); ++i) {
- base::Version version(cases[i].input);
- EXPECT_EQ(cases[i].success, version.IsValid());
- if (cases[i].success) {
- EXPECT_EQ(cases[i].parts, version.components().size());
- EXPECT_EQ(cases[i].firstpart, version.components()[0]);
- }
- }
-}
-
-TEST(VersionTest, Compare) {
- static const struct version_compare {
- const char* lhs;
- const char* rhs;
- int expected;
- } cases[] = {
- {"1.0", "1.0", 0},
- {"1.0", "0.0", 1},
- {"1.0", "2.0", -1},
- {"1.0", "1.1", -1},
- {"1.1", "1.0", 1},
- {"1.0", "1.0.1", -1},
- {"1.1", "1.0.1", 1},
- {"1.1", "1.0.1", 1},
- {"1.0.0", "1.0", 0},
- {"1.0.3", "1.0.20", -1},
- {"11.0.10", "15.007.20011", -1},
- {"11.0.10", "15.5.28.130162", -1},
- {"15.5.28.130162", "15.5.28.130162", 0},
- };
- for (size_t i = 0; i < arraysize(cases); ++i) {
- base::Version lhs(cases[i].lhs);
- base::Version rhs(cases[i].rhs);
- EXPECT_EQ(lhs.CompareTo(rhs), cases[i].expected) <<
- cases[i].lhs << " ? " << cases[i].rhs;
- // CompareToWildcardString() should have same behavior as CompareTo() when
- // no wildcards are present.
- EXPECT_EQ(lhs.CompareToWildcardString(cases[i].rhs), cases[i].expected)
- << cases[i].lhs << " ? " << cases[i].rhs;
- EXPECT_EQ(rhs.CompareToWildcardString(cases[i].lhs), -cases[i].expected)
- << cases[i].lhs << " ? " << cases[i].rhs;
-
- // Test comparison operators
- switch (cases[i].expected) {
- case -1:
- EXPECT_LT(lhs, rhs);
- EXPECT_LE(lhs, rhs);
- EXPECT_NE(lhs, rhs);
- EXPECT_FALSE(lhs == rhs);
- EXPECT_FALSE(lhs >= rhs);
- EXPECT_FALSE(lhs > rhs);
- break;
- case 0:
- EXPECT_FALSE(lhs < rhs);
- EXPECT_LE(lhs, rhs);
- EXPECT_FALSE(lhs != rhs);
- EXPECT_EQ(lhs, rhs);
- EXPECT_GE(lhs, rhs);
- EXPECT_FALSE(lhs > rhs);
- break;
- case 1:
- EXPECT_FALSE(lhs < rhs);
- EXPECT_FALSE(lhs <= rhs);
- EXPECT_NE(lhs, rhs);
- EXPECT_FALSE(lhs == rhs);
- EXPECT_GE(lhs, rhs);
- EXPECT_GT(lhs, rhs);
- break;
- }
- }
-}
-
-TEST(VersionTest, CompareToWildcardString) {
- static const struct version_compare {
- const char* lhs;
- const char* rhs;
- int expected;
- } cases[] = {
- {"1.0", "1.*", 0},
- {"1.0", "0.*", 1},
- {"1.0", "2.*", -1},
- {"1.2.3", "1.2.3.*", 0},
- {"10.0", "1.0.*", 1},
- {"1.0", "3.0.*", -1},
- {"1.4", "1.3.0.*", 1},
- {"1.3.9", "1.3.*", 0},
- {"1.4.1", "1.3.*", 1},
- {"1.3", "1.4.5.*", -1},
- {"1.5", "1.4.5.*", 1},
- {"1.3.9", "1.3.*", 0},
- {"1.2.0.0.0.0", "1.2.*", 0},
- };
- for (size_t i = 0; i < arraysize(cases); ++i) {
- const base::Version version(cases[i].lhs);
- const int result = version.CompareToWildcardString(cases[i].rhs);
- EXPECT_EQ(result, cases[i].expected) << cases[i].lhs << "?" << cases[i].rhs;
- }
-}
-
-TEST(VersionTest, IsValidWildcardString) {
- static const struct version_compare {
- const char* version;
- bool expected;
- } cases[] = {
- {"1.0", true},
- {"", false},
- {"1.2.3.4.5.6", true},
- {"1.2.3.*", true},
- {"1.2.3.5*", false},
- {"1.2.3.56*", false},
- {"1.*.3", false},
- {"20.*", true},
- {"+2.*", false},
- {"*", false},
- {"*.2", false},
- };
- for (size_t i = 0; i < arraysize(cases); ++i) {
- EXPECT_EQ(base::Version::IsValidWildcardString(cases[i].version),
- cases[i].expected) << cases[i].version << "?" << cases[i].expected;
- }
-}
-
-} // namespace
diff --git a/base/vlog_unittest.cc b/base/vlog_unittest.cc
deleted file mode 100644
index 3c3f49c..0000000
--- a/base/vlog_unittest.cc
+++ /dev/null
@@ -1,124 +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/vlog.h"
-
-#include "base/logging.h"
-#include "base/time/time.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace logging {
-
-namespace {
-
-TEST(VlogTest, NoVmodule) {
- int min_log_level = 0;
- EXPECT_EQ(0,
- VlogInfo(std::string(), std::string(), &min_log_level)
- .GetVlogLevel("test1"));
- EXPECT_EQ(0,
- VlogInfo("0", std::string(), &min_log_level).GetVlogLevel("test2"));
- EXPECT_EQ(
- 0, VlogInfo("blah", std::string(), &min_log_level).GetVlogLevel("test3"));
- EXPECT_EQ(
- 0,
- VlogInfo("0blah1", std::string(), &min_log_level).GetVlogLevel("test4"));
- EXPECT_EQ(1,
- VlogInfo("1", std::string(), &min_log_level).GetVlogLevel("test5"));
- EXPECT_EQ(5,
- VlogInfo("5", std::string(), &min_log_level).GetVlogLevel("test6"));
-}
-
-TEST(VlogTest, MatchVlogPattern) {
- // Degenerate cases.
- EXPECT_TRUE(MatchVlogPattern("", ""));
- EXPECT_TRUE(MatchVlogPattern("", "****"));
- EXPECT_FALSE(MatchVlogPattern("", "x"));
- EXPECT_FALSE(MatchVlogPattern("x", ""));
-
- // Basic.
- EXPECT_TRUE(MatchVlogPattern("blah", "blah"));
-
- // ? should match exactly one character.
- EXPECT_TRUE(MatchVlogPattern("blah", "bl?h"));
- EXPECT_FALSE(MatchVlogPattern("blh", "bl?h"));
- EXPECT_FALSE(MatchVlogPattern("blaah", "bl?h"));
- EXPECT_TRUE(MatchVlogPattern("blah", "?lah"));
- EXPECT_FALSE(MatchVlogPattern("lah", "?lah"));
- EXPECT_FALSE(MatchVlogPattern("bblah", "?lah"));
-
- // * can match any number (even 0) of characters.
- EXPECT_TRUE(MatchVlogPattern("blah", "bl*h"));
- EXPECT_TRUE(MatchVlogPattern("blabcdefh", "bl*h"));
- EXPECT_TRUE(MatchVlogPattern("blh", "bl*h"));
- EXPECT_TRUE(MatchVlogPattern("blah", "*blah"));
- EXPECT_TRUE(MatchVlogPattern("ohblah", "*blah"));
- EXPECT_TRUE(MatchVlogPattern("blah", "blah*"));
- EXPECT_TRUE(MatchVlogPattern("blahhhh", "blah*"));
- EXPECT_TRUE(MatchVlogPattern("blahhhh", "blah*"));
- EXPECT_TRUE(MatchVlogPattern("blah", "*blah*"));
- EXPECT_TRUE(MatchVlogPattern("blahhhh", "*blah*"));
- EXPECT_TRUE(MatchVlogPattern("bbbblahhhh", "*blah*"));
-
- // Multiple *s should work fine.
- EXPECT_TRUE(MatchVlogPattern("ballaah", "b*la*h"));
- EXPECT_TRUE(MatchVlogPattern("blah", "b*la*h"));
- EXPECT_TRUE(MatchVlogPattern("bbbblah", "b*la*h"));
- EXPECT_TRUE(MatchVlogPattern("blaaah", "b*la*h"));
-
- // There should be no escaping going on.
- EXPECT_TRUE(MatchVlogPattern("bl\\ah", "bl\\?h"));
- EXPECT_FALSE(MatchVlogPattern("bl?h", "bl\\?h"));
- EXPECT_TRUE(MatchVlogPattern("bl\\aaaah", "bl\\*h"));
- EXPECT_FALSE(MatchVlogPattern("bl*h", "bl\\*h"));
-
- // Any slash matches any slash.
- EXPECT_TRUE(MatchVlogPattern("/b\\lah", "/b\\lah"));
- EXPECT_TRUE(MatchVlogPattern("\\b/lah", "/b\\lah"));
-}
-
-TEST(VlogTest, VmoduleBasic) {
- const char kVSwitch[] = "-1";
- const char kVModuleSwitch[] =
- "foo=,bar=0,baz=blah,,qux=0blah1,quux=1,corge.ext=5";
- int min_log_level = 0;
- VlogInfo vlog_info(kVSwitch, kVModuleSwitch, &min_log_level);
- EXPECT_EQ(-1, vlog_info.GetVlogLevel("/path/to/grault.cc"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("/path/to/foo.cc"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("D:\\Path\\To\\bar-inl.mm"));
- EXPECT_EQ(-1, vlog_info.GetVlogLevel("D:\\path\\to what/bar_unittest.m"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("baz.h"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("/another/path/to/qux.h"));
- EXPECT_EQ(1, vlog_info.GetVlogLevel("/path/to/quux"));
- EXPECT_EQ(5, vlog_info.GetVlogLevel("c:\\path/to/corge.ext.h"));
-}
-
-TEST(VlogTest, VmoduleDirs) {
- const char kVModuleSwitch[] =
- "foo/bar.cc=1,baz\\*\\qux.cc=2,*quux/*=3,*/*-inl.h=4";
- int min_log_level = 0;
- VlogInfo vlog_info(std::string(), kVModuleSwitch, &min_log_level);
- EXPECT_EQ(0, vlog_info.GetVlogLevel("/foo/bar.cc"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("bar.cc"));
- EXPECT_EQ(1, vlog_info.GetVlogLevel("foo/bar.cc"));
-
- EXPECT_EQ(0, vlog_info.GetVlogLevel("baz/grault/qux.h"));
- EXPECT_EQ(0, vlog_info.GetVlogLevel("/baz/grault/qux.cc"));
- EXPECT_EQ(2, vlog_info.GetVlogLevel("baz/grault/qux.cc"));
- EXPECT_EQ(2, vlog_info.GetVlogLevel("baz/grault/blah/qux.cc"));
- EXPECT_EQ(2, vlog_info.GetVlogLevel("baz\\grault\\qux.cc"));
- EXPECT_EQ(2, vlog_info.GetVlogLevel("baz\\grault//blah\\qux.cc"));
-
- EXPECT_EQ(0, vlog_info.GetVlogLevel("/foo/bar/baz/quux.cc"));
- EXPECT_EQ(3, vlog_info.GetVlogLevel("/foo/bar/baz/quux/grault.cc"));
- EXPECT_EQ(3, vlog_info.GetVlogLevel("/foo\\bar/baz\\quux/grault.cc"));
-
- EXPECT_EQ(0, vlog_info.GetVlogLevel("foo/bar/test-inl.cc"));
- EXPECT_EQ(4, vlog_info.GetVlogLevel("foo/bar/test-inl.h"));
- EXPECT_EQ(4, vlog_info.GetVlogLevel("foo/bar/baz/blah-inl.h"));
-}
-
-} // namespace
-
-} // namespace logging
diff --git a/base/win/BUILD.gn b/base/win/BUILD.gn
deleted file mode 100644
index 19c2982..0000000
--- a/base/win/BUILD.gn
+++ /dev/null
@@ -1,32 +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.
-
-import("//build/buildflag_header.gni")
-
-declare_args() {
- # Indicates if the handle verifier should operate in a single module mode. By
- # default a single instance gets shared by all the modules.
- single_module_mode_handle_verifier = false
-}
-
-# Ensure that the handle verifier is always used in a single module mode for the
-# component builds.
-if (is_component_build) {
- single_module_mode_handle_verifier = true
-}
-
-buildflag_header("base_win_buildflags") {
- header = "base_win_buildflags.h"
- header_dir = "base/win"
- flags = [
- "SINGLE_MODULE_MODE_HANDLE_VERIFIER=$single_module_mode_handle_verifier",
- ]
-}
-
-static_library("pe_image") {
- sources = [
- "pe_image.cc",
- "pe_image.h",
- ]
-}
diff --git a/base/win/async_operation_unittest.cc b/base/win/async_operation_unittest.cc
deleted file mode 100644
index b29e181..0000000
--- a/base/win/async_operation_unittest.cc
+++ /dev/null
@@ -1,174 +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/win/async_operation.h"
-
-#include <utility>
-
-#include "base/test/gtest_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace WRL = Microsoft::WRL;
-
-using ABI::Windows::Foundation::IAsyncOperation;
-using ABI::Windows::Foundation::IAsyncOperationCompletedHandler;
-
-// In order to exercise the interface logic of AsyncOperation we define an empty
-// dummy interface, its implementation, and the necessary boilerplate to hook it
-// up with IAsyncOperation and IAsyncOperationCompletedHandler.
-namespace {
-
-// Chosen by fair `uuidgen` invocation. Also applies to the UUIDs below.
-MIDL_INTERFACE("756358C7-8083-4D78-9D27-9278B76096d4")
-IFooBar : public IInspectable{};
-
-class FooBar
- : public WRL::RuntimeClass<
- WRL::RuntimeClassFlags<WRL::WinRt | WRL::InhibitRoOriginateError>,
- IFooBar> {};
-
-} // namespace
-
-namespace ABI {
-namespace Windows {
-namespace Foundation {
-
-// Provide the required template specializations to register
-// IAsyncOperation<Foobar*> as an AggregateType. This is similar to how it is
-// done for UWP classes.
-template <>
-struct DECLSPEC_UUID("124858e4-f97e-409c-86ae-418c4781144c")
- IAsyncOperation<FooBar*>
- : IAsyncOperation_impl<Internal::AggregateType<FooBar*, IFooBar*>> {
- static const wchar_t* z_get_rc_name_impl() {
- return L"Windows.Foundation.IAsyncOperation<FooBar>";
- }
-};
-
-template <>
-struct DECLSPEC_UUID("9e49373c-200c-4715-abd7-4214ba669c81")
- IAsyncOperationCompletedHandler<FooBar*>
- : IAsyncOperationCompletedHandler_impl<
- Internal::AggregateType<FooBar*, IFooBar*>> {
- static const wchar_t* z_get_rc_name_impl() {
- return L"Windows.Foundation.AsyncOperationCompletedHandler<FooBar>";
- }
-};
-
-} // namespace Foundation
-} // namespace Windows
-} // namespace ABI
-
-namespace base {
-namespace win {
-
-namespace {
-
-// Utility method to add a completion callback to |async_op|. |*called_cb| will
-// be set to true once the callback is invoked.
-template <typename T>
-void PutCallback(AsyncOperation<T>* async_op, bool* called_cb) {
- async_op->put_Completed(
- WRL::Callback<IAsyncOperationCompletedHandler<T>>(
- [=](IAsyncOperation<T>* iasync_op, AsyncStatus status) {
- EXPECT_EQ(async_op, iasync_op);
- *called_cb = true;
- return S_OK;
- })
- .Get());
-}
-
-} // namespace
-
-TEST(AsyncOperationTest, TestInt) {
- bool called_cb = false;
-
- auto int_op = WRL::Make<AsyncOperation<int>>();
- PutCallback(int_op.Get(), &called_cb);
-
- int results;
- EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
- EXPECT_FALSE(called_cb);
- int_op->callback().Run(123);
-
- EXPECT_TRUE(called_cb);
- EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
- EXPECT_EQ(123, results);
-
- // GetResults should be idempotent.
- EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
- EXPECT_EQ(123, results);
-}
-
-TEST(AsyncOperationTest, TestBool) {
- bool called_cb = false;
-
- auto bool_op = WRL::Make<AsyncOperation<bool>>();
- PutCallback(bool_op.Get(), &called_cb);
-
- // AsyncOperation<bool> is an aggregate of bool and boolean, and requires a
- // pointer to the latter to get the results.
- boolean results;
- EXPECT_TRUE(FAILED(bool_op->GetResults(&results)));
- EXPECT_FALSE(called_cb);
- bool_op->callback().Run(true);
-
- EXPECT_TRUE(called_cb);
- EXPECT_TRUE(SUCCEEDED(bool_op->GetResults(&results)));
- EXPECT_TRUE(results);
-}
-
-TEST(AsyncOperationTest, TestInterface) {
- bool called_cb = false;
-
- auto foobar_op = WRL::Make<AsyncOperation<FooBar*>>();
- PutCallback(foobar_op.Get(), &called_cb);
-
- // AsyncOperation<FooBar*> is an aggregate of FooBar* and IFooBar*.
- WRL::ComPtr<IFooBar> results;
- EXPECT_TRUE(FAILED(foobar_op->GetResults(&results)));
- EXPECT_FALSE(called_cb);
-
- auto foobar = WRL::Make<FooBar>();
- IFooBar* foobar_ptr = foobar.Get();
- foobar_op->callback().Run(std::move(foobar));
-
- EXPECT_TRUE(called_cb);
- EXPECT_TRUE(SUCCEEDED(foobar_op->GetResults(&results)));
- EXPECT_EQ(foobar_ptr, results.Get());
-}
-
-TEST(AsyncOperationTest, TestIdempotence) {
- bool called_cb = false;
-
- auto int_op = WRL::Make<AsyncOperation<int>>();
- PutCallback(int_op.Get(), &called_cb);
-
- int results;
- EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
- EXPECT_FALSE(called_cb);
- // Calling GetResults twice shouldn't change the result.
- EXPECT_TRUE(FAILED(int_op->GetResults(&results)));
- EXPECT_FALSE(called_cb);
-
- int_op->callback().Run(42);
-
- EXPECT_TRUE(called_cb);
- EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
- EXPECT_EQ(42, results);
- // Calling GetResults twice shouldn't change the result.
- EXPECT_TRUE(SUCCEEDED(int_op->GetResults(&results)));
- EXPECT_EQ(42, results);
-}
-
-TEST(AsyncOperationTest, DoubleCallbackFails) {
- auto int_op = WRL::Make<AsyncOperation<int>>();
- auto cb = int_op->callback();
-
- // Obtaining another callback should result in a DCHECK failure.
- EXPECT_DCHECK_DEATH(int_op->callback());
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/com_init_check_hook_unittest.cc b/base/win/com_init_check_hook_unittest.cc
deleted file mode 100644
index 32aede4..0000000
--- a/base/win/com_init_check_hook_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/win/com_init_check_hook.h"
-
-#include <objbase.h>
-#include <shlobj.h>
-#include <wrl/client.h>
-
-#include "base/test/gtest_util.h"
-#include "base/win/com_init_util.h"
-#include "base/win/patch_util.h"
-#include "base/win/scoped_com_initializer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-using Microsoft::WRL::ComPtr;
-
-TEST(ComInitCheckHook, AssertNotInitialized) {
- ComInitCheckHook com_check_hook;
- AssertComApartmentType(ComApartmentType::NONE);
- ComPtr<IUnknown> shell_link;
-#if defined(COM_INIT_CHECK_HOOK_ENABLED)
- EXPECT_DCHECK_DEATH(::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
-#else
- EXPECT_EQ(CO_E_NOTINITIALIZED,
- ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
-#endif
-}
-
-TEST(ComInitCheckHook, HookRemoval) {
- AssertComApartmentType(ComApartmentType::NONE);
- { ComInitCheckHook com_check_hook; }
- ComPtr<IUnknown> shell_link;
- EXPECT_EQ(CO_E_NOTINITIALIZED,
- ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
-}
-
-TEST(ComInitCheckHook, NoAssertComInitialized) {
- ComInitCheckHook com_check_hook;
- ScopedCOMInitializer com_initializer;
- ComPtr<IUnknown> shell_link;
- EXPECT_TRUE(SUCCEEDED(::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link))));
-}
-
-TEST(ComInitCheckHook, MultipleHooks) {
- ComInitCheckHook com_check_hook_1;
- ComInitCheckHook com_check_hook_2;
- AssertComApartmentType(ComApartmentType::NONE);
- ComPtr<IUnknown> shell_link;
-#if defined(COM_INIT_CHECK_HOOK_ENABLED)
- EXPECT_DCHECK_DEATH(::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
-#else
- EXPECT_EQ(CO_E_NOTINITIALIZED,
- ::CoCreateInstance(CLSID_ShellLink, nullptr, CLSCTX_ALL,
- IID_PPV_ARGS(&shell_link)));
-#endif
-}
-
-TEST(ComInitCheckHook, UnexpectedHook) {
-#if defined(COM_INIT_CHECK_HOOK_ENABLED)
- HMODULE ole32_library = ::LoadLibrary(L"ole32.dll");
- ASSERT_TRUE(ole32_library);
-
- uint32_t co_create_instance_padded_address =
- reinterpret_cast<uint32_t>(
- GetProcAddress(ole32_library, "CoCreateInstance")) - 5;
- const unsigned char* co_create_instance_bytes =
- reinterpret_cast<const unsigned char*>(co_create_instance_padded_address);
- const unsigned char original_byte = co_create_instance_bytes[0];
- const unsigned char unexpected_byte = 0xdb;
- ASSERT_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&unexpected_byte),
- sizeof(unexpected_byte)));
-
- EXPECT_DCHECK_DEATH({ ComInitCheckHook com_check_hook; });
-
- // If this call fails, really bad things are going to happen to other tests
- // so CHECK here.
- CHECK_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_padded_address),
- reinterpret_cast<const void*>(&original_byte),
- sizeof(original_byte)));
-
- ::FreeLibrary(ole32_library);
- ole32_library = nullptr;
-#endif
-}
-
-TEST(ComInitCheckHook, ExternallyHooked) {
-#if defined(COM_INIT_CHECK_HOOK_ENABLED)
- HMODULE ole32_library = ::LoadLibrary(L"ole32.dll");
- ASSERT_TRUE(ole32_library);
-
- uint32_t co_create_instance_address = reinterpret_cast<uint32_t>(
- GetProcAddress(ole32_library, "CoCreateInstance"));
- const unsigned char* co_create_instance_bytes =
- reinterpret_cast<const unsigned char*>(co_create_instance_address);
- const unsigned char original_byte = co_create_instance_bytes[0];
- const unsigned char jmp_byte = 0xe9;
- ASSERT_EQ(static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(
- reinterpret_cast<void*>(co_create_instance_address),
- reinterpret_cast<const void*>(&jmp_byte), sizeof(jmp_byte)));
-
- // Externally patched instances should crash so we catch these cases on bots.
- EXPECT_DCHECK_DEATH({ ComInitCheckHook com_check_hook; });
-
- // If this call fails, really bad things are going to happen to other tests
- // so CHECK here.
- CHECK_EQ(
- static_cast<DWORD>(NO_ERROR),
- internal::ModifyCode(reinterpret_cast<void*>(co_create_instance_address),
- reinterpret_cast<const void*>(&original_byte),
- sizeof(original_byte)));
-
- ::FreeLibrary(ole32_library);
- ole32_library = nullptr;
-#endif
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/com_init_util_unittest.cc b/base/win/com_init_util_unittest.cc
deleted file mode 100644
index fb897dd..0000000
--- a/base/win/com_init_util_unittest.cc
+++ /dev/null
@@ -1,75 +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/win/com_init_util.h"
-
-#include "base/test/gtest_util.h"
-#include "base/win/scoped_com_initializer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-TEST(ComInitUtil, AssertNotInitialized) {
- EXPECT_DCHECK_DEATH(AssertComInitialized());
-}
-
-TEST(ComInitUtil, AssertUninitialized) {
- // When COM is uninitialized, the TLS data will remain, but the apartment
- // status will be updated. This covers that case.
- {
- ScopedCOMInitializer com_initializer;
- ASSERT_TRUE(com_initializer.Succeeded());
- }
- EXPECT_DCHECK_DEATH(AssertComInitialized());
-}
-
-TEST(ComInitUtil, AssertSTAInitialized) {
- ScopedCOMInitializer com_initializer;
- ASSERT_TRUE(com_initializer.Succeeded());
-
- AssertComInitialized();
-}
-
-TEST(ComInitUtil, AssertMTAInitialized) {
- ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
- ASSERT_TRUE(com_initializer.Succeeded());
-
- AssertComInitialized();
-}
-
-TEST(ComInitUtil, AssertNoneApartmentType) {
- AssertComApartmentType(ComApartmentType::NONE);
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA));
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::MTA));
-}
-
-TEST(ComInitUtil, AssertNoneApartmentTypeUninitialized) {
- // When COM is uninitialized, the TLS data will remain, but the apartment
- // status will be updated. This covers that case.
- {
- ScopedCOMInitializer com_initializer;
- ASSERT_TRUE(com_initializer.Succeeded());
- }
- AssertComApartmentType(ComApartmentType::NONE);
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA));
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::MTA));
-}
-
-TEST(ComInitUtil, AssertSTAApartmentType) {
- ScopedCOMInitializer com_initializer;
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::NONE));
- AssertComApartmentType(ComApartmentType::STA);
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::MTA));
-}
-
-TEST(ComInitUtil, AssertMTAApartmentType) {
- ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::NONE));
- EXPECT_DCHECK_DEATH(AssertComApartmentType(ComApartmentType::STA));
- AssertComApartmentType(ComApartmentType::MTA);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/core_winrt_util_unittest.cc b/base/win/core_winrt_util_unittest.cc
deleted file mode 100644
index 11d08b8..0000000
--- a/base/win/core_winrt_util_unittest.cc
+++ /dev/null
@@ -1,34 +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/win/core_winrt_util.h"
-
-#include "base/win/com_init_util.h"
-#include "base/win/scoped_com_initializer.h"
-#include "base/win/windows_version.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-TEST(CoreWinrtUtilTest, PreloadFunctions) {
- if (GetVersion() < VERSION_WIN8)
- EXPECT_FALSE(ResolveCoreWinRTDelayload());
- else
- EXPECT_TRUE(ResolveCoreWinRTDelayload());
-}
-
-TEST(CoreWinrtUtilTest, RoInitializeAndUninitialize) {
- if (GetVersion() < VERSION_WIN8)
- return;
-
- ASSERT_TRUE(ResolveCoreWinRTDelayload());
- ASSERT_HRESULT_SUCCEEDED(base::win::RoInitialize(RO_INIT_MULTITHREADED));
- AssertComApartmentType(ComApartmentType::MTA);
- base::win::RoUninitialize();
- AssertComApartmentType(ComApartmentType::NONE);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/enum_variant_unittest.cc b/base/win/enum_variant_unittest.cc
deleted file mode 100644
index 288c97e..0000000
--- a/base/win/enum_variant_unittest.cc
+++ /dev/null
@@ -1,118 +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/win/enum_variant.h"
-
-#include "base/win/scoped_com_initializer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-TEST(EnumVariantTest, EmptyEnumVariant) {
- ScopedCOMInitializer com_initializer;
-
- EnumVariant* ev = new EnumVariant(0);
- ev->AddRef();
-
- IUnknown* iunknown;
- EXPECT_TRUE(SUCCEEDED(
- ev->QueryInterface(IID_IUnknown, reinterpret_cast<void**>(&iunknown))));
- iunknown->Release();
-
- IEnumVARIANT* ienumvariant;
- EXPECT_TRUE(SUCCEEDED(
- ev->QueryInterface(IID_IEnumVARIANT,
- reinterpret_cast<void**>(&ienumvariant))));
- EXPECT_EQ(ev, ienumvariant);
- ienumvariant->Release();
-
- VARIANT out_element;
- ULONG out_received = 0;
- EXPECT_EQ(S_FALSE, ev->Next(1, &out_element, &out_received));
- EXPECT_EQ(0u, out_received);
-
- EXPECT_EQ(S_FALSE, ev->Skip(1));
-
- EXPECT_EQ(S_OK, ev->Reset());
-
- IEnumVARIANT* ev2 = NULL;
- EXPECT_EQ(S_OK, ev->Clone(&ev2));
-
- EXPECT_NE(static_cast<IEnumVARIANT*>(NULL), ev2);
- EXPECT_NE(ev, ev2);
- EXPECT_EQ(S_FALSE, ev2->Skip(1));
- EXPECT_EQ(S_OK, ev2->Reset());
-
- ULONG ev2_finalrefcount = ev2->Release();
- EXPECT_EQ(0u, ev2_finalrefcount);
-
- ULONG ev_finalrefcount = ev->Release();
- EXPECT_EQ(0u, ev_finalrefcount);
-}
-
-TEST(EnumVariantTest, SimpleEnumVariant) {
- ScopedCOMInitializer com_initializer;
-
- EnumVariant* ev = new EnumVariant(3);
- ev->AddRef();
- ev->ItemAt(0)->vt = VT_I4;
- ev->ItemAt(0)->lVal = 10;
- ev->ItemAt(1)->vt = VT_I4;
- ev->ItemAt(1)->lVal = 20;
- ev->ItemAt(2)->vt = VT_I4;
- ev->ItemAt(2)->lVal = 30;
-
- // Get elements one at a time.
- VARIANT out_element;
- ULONG out_received = 0;
- EXPECT_EQ(S_OK, ev->Next(1, &out_element, &out_received));
- EXPECT_EQ(1u, out_received);
- EXPECT_EQ(VT_I4, out_element.vt);
- EXPECT_EQ(10, out_element.lVal);
- EXPECT_EQ(S_OK, ev->Skip(1));
- EXPECT_EQ(S_OK, ev->Next(1, &out_element, &out_received));
- EXPECT_EQ(1u, out_received);
- EXPECT_EQ(VT_I4, out_element.vt);
- EXPECT_EQ(30, out_element.lVal);
- EXPECT_EQ(S_FALSE, ev->Next(1, &out_element, &out_received));
-
- // Reset and get all elements at once.
- VARIANT out_elements[3];
- EXPECT_EQ(S_OK, ev->Reset());
- EXPECT_EQ(S_OK, ev->Next(3, out_elements, &out_received));
- EXPECT_EQ(3u, out_received);
- EXPECT_EQ(VT_I4, out_elements[0].vt);
- EXPECT_EQ(10, out_elements[0].lVal);
- EXPECT_EQ(VT_I4, out_elements[1].vt);
- EXPECT_EQ(20, out_elements[1].lVal);
- EXPECT_EQ(VT_I4, out_elements[2].vt);
- EXPECT_EQ(30, out_elements[2].lVal);
- EXPECT_EQ(S_FALSE, ev->Next(1, &out_element, &out_received));
-
- // Clone it.
- IEnumVARIANT* ev2 = NULL;
- EXPECT_EQ(S_OK, ev->Clone(&ev2));
- EXPECT_TRUE(ev2 != NULL);
- EXPECT_EQ(S_FALSE, ev->Next(1, &out_element, &out_received));
- EXPECT_EQ(S_OK, ev2->Reset());
- EXPECT_EQ(S_OK, ev2->Next(3, out_elements, &out_received));
- EXPECT_EQ(3u, out_received);
- EXPECT_EQ(VT_I4, out_elements[0].vt);
- EXPECT_EQ(10, out_elements[0].lVal);
- EXPECT_EQ(VT_I4, out_elements[1].vt);
- EXPECT_EQ(20, out_elements[1].lVal);
- EXPECT_EQ(VT_I4, out_elements[2].vt);
- EXPECT_EQ(30, out_elements[2].lVal);
- EXPECT_EQ(S_FALSE, ev2->Next(1, &out_element, &out_received));
-
- ULONG ev2_finalrefcount = ev2->Release();
- EXPECT_EQ(0u, ev2_finalrefcount);
-
- ULONG ev_finalrefcount = ev->Release();
- EXPECT_EQ(0u, ev_finalrefcount);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/event_trace_consumer_unittest.cc b/base/win/event_trace_consumer_unittest.cc
deleted file mode 100644
index 9c4c242..0000000
--- a/base/win/event_trace_consumer_unittest.cc
+++ /dev/null
@@ -1,367 +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.
-//
-// Unit tests for event trace consumer base class.
-#include "base/win/event_trace_consumer.h"
-
-#include <list>
-
-#include <objbase.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/process/process_handle.h"
-#include "base/strings/stringprintf.h"
-#include "base/win/event_trace_controller.h"
-#include "base/win/event_trace_provider.h"
-#include "base/win/scoped_handle.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include <initguid.h> // NOLINT - has to be last
-
-namespace base {
-namespace win {
-
-namespace {
-
-typedef std::list<EVENT_TRACE> EventQueue;
-
-class TestConsumer: public EtwTraceConsumerBase<TestConsumer> {
- public:
- TestConsumer() {
- sank_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
- ClearQueue();
- }
-
- ~TestConsumer() {
- ClearQueue();
- sank_event_.Close();
- }
-
- void ClearQueue() {
- for (EventQueue::const_iterator it(events_.begin()), end(events_.end());
- it != end; ++it) {
- delete[] reinterpret_cast<char*>(it->MofData);
- }
-
- events_.clear();
- }
-
- static void EnqueueEvent(EVENT_TRACE* event) {
- events_.push_back(*event);
- EVENT_TRACE& back = events_.back();
-
- if (event->MofData != NULL && event->MofLength != 0) {
- back.MofData = new char[event->MofLength];
- memcpy(back.MofData, event->MofData, event->MofLength);
- }
- }
-
- static void ProcessEvent(EVENT_TRACE* event) {
- EnqueueEvent(event);
- ::SetEvent(sank_event_.Get());
- }
-
- static ScopedHandle sank_event_;
- static EventQueue events_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(TestConsumer);
-};
-
-ScopedHandle TestConsumer::sank_event_;
-EventQueue TestConsumer::events_;
-
-class EtwTraceConsumerBaseTest: public testing::Test {
- public:
- EtwTraceConsumerBaseTest()
- : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
- }
-
- void SetUp() override {
- // Cleanup any potentially dangling sessions.
- EtwTraceProperties ignore;
- EtwTraceController::Stop(session_name_.c_str(), &ignore);
-
- // Allocate a new GUID for each provider test.
- ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
- }
-
- void TearDown() override {
- // Cleanup any potentially dangling sessions.
- EtwTraceProperties ignore;
- EtwTraceController::Stop(session_name_.c_str(), &ignore);
- }
-
- protected:
- GUID test_provider_;
- std::wstring session_name_;
-};
-
-} // namespace
-
-TEST_F(EtwTraceConsumerBaseTest, Initialize) {
- TestConsumer consumer_;
-}
-
-TEST_F(EtwTraceConsumerBaseTest, OpenRealtimeSucceedsWhenNoSession) {
- TestConsumer consumer_;
- ASSERT_HRESULT_SUCCEEDED(
- consumer_.OpenRealtimeSession(session_name_.c_str()));
-}
-
-TEST_F(EtwTraceConsumerBaseTest, ConsumerImmediateFailureWhenNoSession) {
- TestConsumer consumer_;
- ASSERT_HRESULT_SUCCEEDED(
- consumer_.OpenRealtimeSession(session_name_.c_str()));
- ASSERT_HRESULT_FAILED(consumer_.Consume());
-}
-
-namespace {
-
-class EtwTraceConsumerRealtimeTest: public EtwTraceConsumerBaseTest {
- public:
- void SetUp() override {
- EtwTraceConsumerBaseTest::SetUp();
- ASSERT_HRESULT_SUCCEEDED(
- consumer_.OpenRealtimeSession(session_name_.c_str()));
- }
-
- void TearDown() override {
- consumer_.Close();
- EtwTraceConsumerBaseTest::TearDown();
- }
-
- DWORD ConsumerThread() {
- ::SetEvent(consumer_ready_.Get());
- return consumer_.Consume();
- }
-
- static DWORD WINAPI ConsumerThreadMainProc(void* arg) {
- return reinterpret_cast<EtwTraceConsumerRealtimeTest*>(arg)->
- ConsumerThread();
- }
-
- HRESULT StartConsumerThread() {
- consumer_ready_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
- EXPECT_TRUE(consumer_ready_.IsValid());
- consumer_thread_.Set(::CreateThread(NULL, 0, ConsumerThreadMainProc, this,
- 0, NULL));
- if (consumer_thread_.Get() == NULL)
- return HRESULT_FROM_WIN32(::GetLastError());
-
- HANDLE events[] = { consumer_ready_.Get(), consumer_thread_.Get() };
- DWORD result = ::WaitForMultipleObjects(arraysize(events), events,
- FALSE, INFINITE);
- switch (result) {
- case WAIT_OBJECT_0:
- // The event was set, the consumer_ is ready.
- return S_OK;
- case WAIT_OBJECT_0 + 1: {
- // The thread finished. This may race with the event, so check
- // explicitly for the event here, before concluding there's trouble.
- if (::WaitForSingleObject(consumer_ready_.Get(), 0) == WAIT_OBJECT_0)
- return S_OK;
- DWORD exit_code = 0;
- if (::GetExitCodeThread(consumer_thread_.Get(), &exit_code))
- return exit_code;
- return HRESULT_FROM_WIN32(::GetLastError());
- }
- default:
- return E_UNEXPECTED;
- }
- }
-
- // Waits for consumer_ thread to exit, and returns its exit code.
- HRESULT JoinConsumerThread() {
- if (::WaitForSingleObject(consumer_thread_.Get(), INFINITE) !=
- WAIT_OBJECT_0) {
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- DWORD exit_code = 0;
- if (::GetExitCodeThread(consumer_thread_.Get(), &exit_code))
- return exit_code;
-
- return HRESULT_FROM_WIN32(::GetLastError());
- }
-
- TestConsumer consumer_;
- ScopedHandle consumer_ready_;
- ScopedHandle consumer_thread_;
-};
-
-} // namespace
-
-TEST_F(EtwTraceConsumerRealtimeTest, ConsumerReturnsWhenSessionClosed) {
- EtwTraceController controller;
- if (controller.StartRealtimeSession(session_name_.c_str(), 100 * 1024) ==
- E_ACCESSDENIED) {
- VLOG(1) << "You must be an administrator to run this test on Vista";
- return;
- }
-
- // Start the consumer_.
- ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
-
- // Wait around for the consumer_ thread a bit.
- ASSERT_EQ(static_cast<DWORD>(WAIT_TIMEOUT),
- ::WaitForSingleObject(consumer_thread_.Get(), 50));
- ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
-
- // The consumer_ returns success on session stop.
- ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
-}
-
-namespace {
-
-// {57E47923-A549-476f-86CA-503D57F59E62}
-DEFINE_GUID(
- kTestEventType,
- 0x57e47923, 0xa549, 0x476f, 0x86, 0xca, 0x50, 0x3d, 0x57, 0xf5, 0x9e, 0x62);
-
-} // namespace
-
-TEST_F(EtwTraceConsumerRealtimeTest, ConsumeEvent) {
- EtwTraceController controller;
- if (controller.StartRealtimeSession(session_name_.c_str(), 100 * 1024) ==
- E_ACCESSDENIED) {
- VLOG(1) << "You must be an administrator to run this test on Vista";
- return;
- }
-
- ASSERT_HRESULT_SUCCEEDED(controller.EnableProvider(
- test_provider_, TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
-
- EtwTraceProvider provider(test_provider_);
- ASSERT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Register());
-
- // Start the consumer_.
- ASSERT_HRESULT_SUCCEEDED(StartConsumerThread());
- ASSERT_EQ(0u, TestConsumer::events_.size());
-
- EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
- EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Log(&event.header));
- EXPECT_EQ(WAIT_OBJECT_0,
- ::WaitForSingleObject(TestConsumer::sank_event_.Get(), INFINITE));
- ASSERT_HRESULT_SUCCEEDED(controller.Stop(NULL));
- ASSERT_HRESULT_SUCCEEDED(JoinConsumerThread());
- ASSERT_NE(0u, TestConsumer::events_.size());
-}
-
-namespace {
-
-// We run events through a file session to assert that
-// the content comes through.
-class EtwTraceConsumerDataTest: public EtwTraceConsumerBaseTest {
- public:
- EtwTraceConsumerDataTest() {
- }
-
- void SetUp() override {
- EtwTraceConsumerBaseTest::SetUp();
-
- EtwTraceProperties prop;
- EtwTraceController::Stop(session_name_.c_str(), &prop);
-
- // Create a temp dir for this test.
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- // Construct a temp file name in our dir.
- temp_file_ = temp_dir_.GetPath().Append(L"test.etl");
- }
-
- void TearDown() override {
- EXPECT_TRUE(base::DeleteFile(temp_file_, false));
-
- EtwTraceConsumerBaseTest::TearDown();
- }
-
- HRESULT LogEventToTempSession(PEVENT_TRACE_HEADER header) {
- EtwTraceController controller;
-
- // Set up a file session.
- HRESULT hr = controller.StartFileSession(session_name_.c_str(),
- temp_file_.value().c_str());
- if (FAILED(hr))
- return hr;
-
- // Enable our provider.
- EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(
- test_provider_, TRACE_LEVEL_VERBOSE, 0xFFFFFFFF));
-
- EtwTraceProvider provider(test_provider_);
- // Then register our provider, means we get a session handle immediately.
- EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Register());
- // Trace the event, it goes to the temp file.
- EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Log(header));
- EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(test_provider_));
- EXPECT_HRESULT_SUCCEEDED(provider.Unregister());
- EXPECT_HRESULT_SUCCEEDED(controller.Flush(NULL));
- EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
-
- return S_OK;
- }
-
- HRESULT ConsumeEventFromTempSession() {
- // Now consume the event(s).
- TestConsumer consumer_;
- HRESULT hr = consumer_.OpenFileSession(temp_file_.value().c_str());
- if (SUCCEEDED(hr))
- hr = consumer_.Consume();
- consumer_.Close();
- // And nab the result.
- events_.swap(TestConsumer::events_);
- return hr;
- }
-
- HRESULT RoundTripEvent(PEVENT_TRACE_HEADER header, PEVENT_TRACE* trace) {
- base::DeleteFile(temp_file_, false);
-
- HRESULT hr = LogEventToTempSession(header);
- if (SUCCEEDED(hr))
- hr = ConsumeEventFromTempSession();
-
- if (FAILED(hr))
- return hr;
-
- // We should now have the event in the queue.
- if (events_.empty())
- return E_FAIL;
-
- *trace = &events_.back();
- return S_OK;
- }
-
- EventQueue events_;
- ScopedTempDir temp_dir_;
- FilePath temp_file_;
-};
-
-} // namespace
-
-
-TEST_F(EtwTraceConsumerDataTest, RoundTrip) {
- EtwMofEvent<1> event(kTestEventType, 1, TRACE_LEVEL_ERROR);
-
- static const char kData[] = "This is but test data";
- event.fields[0].DataPtr = reinterpret_cast<ULONG64>(kData);
- event.fields[0].Length = sizeof(kData);
-
- PEVENT_TRACE trace = NULL;
- HRESULT hr = RoundTripEvent(&event.header, &trace);
- if (hr == E_ACCESSDENIED) {
- VLOG(1) << "You must be an administrator to run this test on Vista";
- return;
- }
- ASSERT_HRESULT_SUCCEEDED(hr) << "RoundTripEvent failed";
- ASSERT_TRUE(trace != NULL);
- ASSERT_EQ(sizeof(kData), trace->MofLength);
- ASSERT_STREQ(kData, reinterpret_cast<const char*>(trace->MofData));
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/event_trace_controller_unittest.cc b/base/win/event_trace_controller_unittest.cc
deleted file mode 100644
index f19ee31..0000000
--- a/base/win/event_trace_controller_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.
-//
-// Unit tests for event trace controller.
-
-#include <objbase.h>
-#include <initguid.h>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/process/process_handle.h"
-#include "base/strings/stringprintf.h"
-#include "base/sys_info.h"
-#include "base/win/event_trace_controller.h"
-#include "base/win/event_trace_provider.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/windows_version.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-DEFINE_GUID(kGuidNull,
- 0x0000000, 0x0000, 0x0000, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0);
-
-const ULONG kTestProviderFlags = 0xCAFEBABE;
-
-class TestingProvider: public EtwTraceProvider {
- public:
- explicit TestingProvider(const GUID& provider_name)
- : EtwTraceProvider(provider_name) {
- callback_event_.Set(::CreateEvent(NULL, TRUE, FALSE, NULL));
- }
-
- void WaitForCallback() {
- ::WaitForSingleObject(callback_event_.Get(), INFINITE);
- ::ResetEvent(callback_event_.Get());
- }
-
- private:
- void OnEventsEnabled() override { ::SetEvent(callback_event_.Get()); }
- void PostEventsDisabled() override { ::SetEvent(callback_event_.Get()); }
-
- ScopedHandle callback_event_;
-
- DISALLOW_COPY_AND_ASSIGN(TestingProvider);
-};
-
-} // namespace
-
-TEST(EtwTracePropertiesTest, Initialization) {
- EtwTraceProperties prop;
-
- EVENT_TRACE_PROPERTIES* p = prop.get();
- EXPECT_NE(0u, p->Wnode.BufferSize);
- EXPECT_EQ(0u, p->Wnode.ProviderId);
- EXPECT_EQ(0u, p->Wnode.HistoricalContext);
-
- EXPECT_TRUE(kGuidNull == p->Wnode.Guid);
- EXPECT_EQ(0u, p->Wnode.ClientContext);
- EXPECT_EQ(static_cast<ULONG>(WNODE_FLAG_TRACED_GUID), p->Wnode.Flags);
-
- EXPECT_EQ(0u, p->BufferSize);
- EXPECT_EQ(0u, p->MinimumBuffers);
- EXPECT_EQ(0u, p->MaximumBuffers);
- EXPECT_EQ(0u, p->MaximumFileSize);
- EXPECT_EQ(0u, p->LogFileMode);
- EXPECT_EQ(0u, p->FlushTimer);
- EXPECT_EQ(0u, p->EnableFlags);
- EXPECT_EQ(0, p->AgeLimit);
-
- EXPECT_EQ(0u, p->NumberOfBuffers);
- EXPECT_EQ(0u, p->FreeBuffers);
- EXPECT_EQ(0u, p->EventsLost);
- EXPECT_EQ(0u, p->BuffersWritten);
- EXPECT_EQ(0u, p->LogBuffersLost);
- EXPECT_EQ(0u, p->RealTimeBuffersLost);
- EXPECT_EQ(0u, p->LoggerThreadId);
- EXPECT_NE(0u, p->LogFileNameOffset);
- EXPECT_NE(0u, p->LoggerNameOffset);
-}
-
-TEST(EtwTracePropertiesTest, Strings) {
- EtwTraceProperties prop;
-
- ASSERT_STREQ(L"", prop.GetLoggerFileName());
- ASSERT_STREQ(L"", prop.GetLoggerName());
-
- std::wstring name(1023, L'A');
- ASSERT_HRESULT_SUCCEEDED(prop.SetLoggerFileName(name.c_str()));
- ASSERT_HRESULT_SUCCEEDED(prop.SetLoggerName(name.c_str()));
- ASSERT_STREQ(name.c_str(), prop.GetLoggerFileName());
- ASSERT_STREQ(name.c_str(), prop.GetLoggerName());
-
- std::wstring name2(1024, L'A');
- ASSERT_HRESULT_FAILED(prop.SetLoggerFileName(name2.c_str()));
- ASSERT_HRESULT_FAILED(prop.SetLoggerName(name2.c_str()));
-}
-
-namespace {
-
-class EtwTraceControllerTest : public testing::Test {
- public:
- EtwTraceControllerTest()
- : session_name_(StringPrintf(L"TestSession-%d", GetCurrentProcId())) {
- }
-
- void SetUp() override {
- EtwTraceProperties ignore;
- EtwTraceController::Stop(session_name_.c_str(), &ignore);
-
- // Allocate a new provider name GUID for each test.
- ASSERT_HRESULT_SUCCEEDED(::CoCreateGuid(&test_provider_));
- }
-
- void TearDown() override {
- EtwTraceProperties prop;
- EtwTraceController::Stop(session_name_.c_str(), &prop);
- }
-
- protected:
- GUID test_provider_;
- std::wstring session_name_;
-};
-
-} // namespace
-
-TEST_F(EtwTraceControllerTest, Initialize) {
- EtwTraceController controller;
-
- EXPECT_EQ(0u, controller.session());
- EXPECT_STREQ(L"", controller.session_name());
-}
-
-
-TEST_F(EtwTraceControllerTest, StartRealTimeSession) {
- EtwTraceController controller;
-
- HRESULT hr = controller.StartRealtimeSession(session_name_.c_str(),
- 100 * 1024);
- if (hr == E_ACCESSDENIED) {
- VLOG(1) << "You must be an administrator to run this test on Vista";
- return;
- }
-
- EXPECT_NE(0u, controller.session());
- EXPECT_STREQ(session_name_.c_str(), controller.session_name());
-
- EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
- EXPECT_EQ(0u, controller.session());
- EXPECT_STREQ(L"", controller.session_name());
-}
-
-TEST_F(EtwTraceControllerTest, StartFileSession) {
- ScopedTempDir temp_dir;
- ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
- FilePath temp;
- ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir.GetPath(), &temp));
-
- EtwTraceController controller;
- HRESULT hr = controller.StartFileSession(session_name_.c_str(),
- temp.value().c_str());
- if (hr == E_ACCESSDENIED) {
- VLOG(1) << "You must be an administrator to run this test on Vista";
- base::DeleteFile(temp, false);
- return;
- }
-
- EXPECT_NE(0u, controller.session());
- EXPECT_STREQ(session_name_.c_str(), controller.session_name());
-
- EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
- EXPECT_EQ(0u, controller.session());
- EXPECT_STREQ(L"", controller.session_name());
- base::DeleteFile(temp, false);
-}
-
-// This test is flaky for unclear reasons. See bugs 525297 and 534184
-TEST_F(EtwTraceControllerTest, DISABLED_EnableDisable) {
- TestingProvider provider(test_provider_);
-
- EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Register());
- EXPECT_EQ(0u, provider.session_handle());
-
- EtwTraceController controller;
- HRESULT hr = controller.StartRealtimeSession(session_name_.c_str(),
- 100 * 1024);
- if (hr == E_ACCESSDENIED) {
- VLOG(1) << "You must be an administrator to run this test on Vista";
- return;
- }
-
- EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(test_provider_,
- TRACE_LEVEL_VERBOSE, kTestProviderFlags));
-
- provider.WaitForCallback();
-
- EXPECT_EQ(TRACE_LEVEL_VERBOSE, provider.enable_level());
- EXPECT_EQ(kTestProviderFlags, provider.enable_flags());
-
- EXPECT_HRESULT_SUCCEEDED(controller.DisableProvider(test_provider_));
-
- provider.WaitForCallback();
-
- EXPECT_EQ(0, provider.enable_level());
- EXPECT_EQ(0u, provider.enable_flags());
-
- EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Unregister());
-
- // Enable the provider again, before registering.
- EXPECT_HRESULT_SUCCEEDED(controller.EnableProvider(test_provider_,
- TRACE_LEVEL_VERBOSE, kTestProviderFlags));
-
- // Register the provider again, the settings above
- // should take immediate effect.
- EXPECT_EQ(static_cast<DWORD>(ERROR_SUCCESS), provider.Register());
-
- EXPECT_EQ(TRACE_LEVEL_VERBOSE, provider.enable_level());
- EXPECT_EQ(kTestProviderFlags, provider.enable_flags());
-
- // Consume the callback event of the previous controller.EnableProvider().
- provider.WaitForCallback();
-
- EXPECT_HRESULT_SUCCEEDED(controller.Stop(NULL));
-
- // Windows 7 does not call the callback when Stop() is called so we
- // can't wait, and enable_level and enable_flags are not zeroed.
- if (base::win::GetVersion() >= VERSION_WIN8) {
- provider.WaitForCallback();
-
- // Session should have wound down.
- EXPECT_EQ(0, provider.enable_level());
- EXPECT_EQ(0u, provider.enable_flags());
- }
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/event_trace_provider_unittest.cc b/base/win/event_trace_provider_unittest.cc
deleted file mode 100644
index 7d57773..0000000
--- a/base/win/event_trace_provider_unittest.cc
+++ /dev/null
@@ -1,110 +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.
-//
-// Unit tests for event trace provider.
-#include "base/win/event_trace_provider.h"
-#include <new>
-#include "testing/gtest/include/gtest/gtest.h"
-#include <initguid.h> // NOLINT - has to be last
-
-namespace {
-
-using base::win::EtwTraceProvider;
-using base::win::EtwMofEvent;
-
-// {7F0FD37F-FA3C-4cd6-9242-DF60967A2CB2}
-DEFINE_GUID(kTestProvider,
- 0x7f0fd37f, 0xfa3c, 0x4cd6, 0x92, 0x42, 0xdf, 0x60, 0x96, 0x7a, 0x2c, 0xb2);
-
-// {7F0FD37F-FA3C-4cd6-9242-DF60967A2CB2}
-DEFINE_GUID(kTestEventClass,
- 0x7f0fd37f, 0xfa3c, 0x4cd6, 0x92, 0x42, 0xdf, 0x60, 0x96, 0x7a, 0x2c, 0xb2);
-
-} // namespace
-
-TEST(EtwTraceProviderTest, ToleratesPreCreateInvocations) {
- // Because the trace provider is used in logging, it's important that
- // it be possible to use static provider instances without regard to
- // whether they've been constructed or destructed.
- // The interface of the class is designed to tolerate this usage.
- char buf[sizeof(EtwTraceProvider)] = {0};
- EtwTraceProvider& provider = reinterpret_cast<EtwTraceProvider&>(buf);
-
- EXPECT_EQ(0u, provider.registration_handle());
- EXPECT_EQ(0u, provider.session_handle());
- EXPECT_EQ(0u, provider.enable_flags());
- EXPECT_EQ(0u, provider.enable_level());
-
- EXPECT_FALSE(provider.ShouldLog(TRACE_LEVEL_FATAL, 0xfffffff));
-
- // We expect these not to crash.
- provider.Log(kTestEventClass, 0, TRACE_LEVEL_FATAL, "foo");
- provider.Log(kTestEventClass, 0, TRACE_LEVEL_FATAL, L"foo");
-
- EtwMofEvent<1> dummy(kTestEventClass, 0, TRACE_LEVEL_FATAL);
- DWORD data = 0;
- dummy.SetField(0, sizeof(data), &data);
- provider.Log(dummy.get());
-
- // Placement-new the provider into our buffer.
- new (buf) EtwTraceProvider(kTestProvider);
-
- // Registration is now safe.
- EXPECT_EQ(static_cast<ULONG>(ERROR_SUCCESS), provider.Register());
-
- // Destruct the instance, this should unregister it.
- provider.EtwTraceProvider::~EtwTraceProvider();
-
- // And post-destruction, all of the above should still be safe.
- EXPECT_EQ(0u, provider.registration_handle());
- EXPECT_EQ(0u, provider.session_handle());
- EXPECT_EQ(0u, provider.enable_flags());
- EXPECT_EQ(0u, provider.enable_level());
-
- EXPECT_FALSE(provider.ShouldLog(TRACE_LEVEL_FATAL, 0xfffffff));
-
- // We expect these not to crash.
- provider.Log(kTestEventClass, 0, TRACE_LEVEL_FATAL, "foo");
- provider.Log(kTestEventClass, 0, TRACE_LEVEL_FATAL, L"foo");
- provider.Log(dummy.get());
-}
-
-TEST(EtwTraceProviderTest, Initialize) {
- EtwTraceProvider provider(kTestProvider);
-
- EXPECT_EQ(0u, provider.registration_handle());
- EXPECT_EQ(0u, provider.session_handle());
- EXPECT_EQ(0u, provider.enable_flags());
- EXPECT_EQ(0u, provider.enable_level());
-}
-
-TEST(EtwTraceProviderTest, Register) {
- EtwTraceProvider provider(kTestProvider);
-
- ASSERT_EQ(static_cast<ULONG>(ERROR_SUCCESS), provider.Register());
- EXPECT_NE(0u, provider.registration_handle());
- ASSERT_EQ(static_cast<ULONG>(ERROR_SUCCESS), provider.Unregister());
- EXPECT_EQ(0u, provider.registration_handle());
-}
-
-TEST(EtwTraceProviderTest, RegisterWithNoNameFails) {
- EtwTraceProvider provider;
-
- EXPECT_TRUE(provider.Register() != ERROR_SUCCESS);
-}
-
-TEST(EtwTraceProviderTest, Enable) {
- EtwTraceProvider provider(kTestProvider);
-
- ASSERT_EQ(static_cast<ULONG>(ERROR_SUCCESS), provider.Register());
- EXPECT_NE(0u, provider.registration_handle());
-
- // No session so far.
- EXPECT_EQ(0u, provider.session_handle());
- EXPECT_EQ(0u, provider.enable_flags());
- EXPECT_EQ(0u, provider.enable_level());
-
- ASSERT_EQ(static_cast<ULONG>(ERROR_SUCCESS), provider.Unregister());
- EXPECT_EQ(0u, provider.registration_handle());
-}
diff --git a/base/win/i18n_unittest.cc b/base/win/i18n_unittest.cc
deleted file mode 100644
index 9af6dbf..0000000
--- a/base/win/i18n_unittest.cc
+++ /dev/null
@@ -1,44 +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.
-
-// This file contains unit tests for Windows internationalization funcs.
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-#include <stddef.h>
-
-#include "base/win/i18n.h"
-#include "base/win/windows_version.h"
-
-namespace base {
-namespace win {
-namespace i18n {
-
-// Tests that at least one user preferred UI language can be obtained.
-TEST(I18NTest, GetUserPreferredUILanguageList) {
- std::vector<std::wstring> languages;
- EXPECT_TRUE(GetUserPreferredUILanguageList(&languages));
- EXPECT_NE(static_cast<std::vector<std::wstring>::size_type>(0),
- languages.size());
- for (std::vector<std::wstring>::const_iterator scan = languages.begin(),
- end = languages.end(); scan != end; ++scan) {
- EXPECT_FALSE((*scan).empty());
- }
-}
-
-// Tests that at least one thread preferred UI language can be obtained.
-TEST(I18NTest, GetThreadPreferredUILanguageList) {
- std::vector<std::wstring> languages;
- EXPECT_TRUE(GetThreadPreferredUILanguageList(&languages));
- EXPECT_NE(static_cast<std::vector<std::wstring>::size_type>(0),
- languages.size());
- for (std::vector<std::wstring>::const_iterator scan = languages.begin(),
- end = languages.end(); scan != end; ++scan) {
- EXPECT_FALSE((*scan).empty());
- }
-}
-
-} // namespace i18n
-} // namespace win
-} // namespace base
diff --git a/base/win/iunknown_impl_unittest.cc b/base/win/iunknown_impl_unittest.cc
deleted file mode 100644
index c6c3539..0000000
--- a/base/win/iunknown_impl_unittest.cc
+++ /dev/null
@@ -1,49 +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/win/iunknown_impl.h"
-
-#include "base/win/scoped_com_initializer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-class TestIUnknownImplSubclass : public IUnknownImpl {
- public:
- TestIUnknownImplSubclass() {
- ++instance_count;
- }
- ~TestIUnknownImplSubclass() override { --instance_count; }
- static int instance_count;
-};
-
-// static
-int TestIUnknownImplSubclass::instance_count = 0;
-
-TEST(IUnknownImplTest, IUnknownImpl) {
- ScopedCOMInitializer com_initializer;
-
- EXPECT_EQ(0, TestIUnknownImplSubclass::instance_count);
- IUnknown* u = new TestIUnknownImplSubclass();
-
- EXPECT_EQ(1, TestIUnknownImplSubclass::instance_count);
-
- EXPECT_EQ(1u, u->AddRef());
- EXPECT_EQ(1u, u->AddRef());
-
- IUnknown* other = NULL;
- EXPECT_EQ(E_NOINTERFACE, u->QueryInterface(
- IID_IDispatch, reinterpret_cast<void**>(&other)));
- EXPECT_EQ(S_OK, u->QueryInterface(
- IID_IUnknown, reinterpret_cast<void**>(&other)));
- other->Release();
-
- EXPECT_EQ(1u, u->Release());
- EXPECT_EQ(0u, u->Release());
- EXPECT_EQ(0, TestIUnknownImplSubclass::instance_count);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/message_window_unittest.cc b/base/win/message_window_unittest.cc
deleted file mode 100644
index 00248bf..0000000
--- a/base/win/message_window_unittest.cc
+++ /dev/null
@@ -1,61 +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/bind.h"
-#include "base/guid.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/message_window.h"
-#include "testing/gmock/include/gmock/gmock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-
-namespace {
-
-bool HandleMessage(
- UINT message, WPARAM wparam, LPARAM lparam, LRESULT* result) {
- // Return |wparam| as the result of WM_USER message.
- if (message == WM_USER) {
- *result = wparam;
- return true;
- }
-
- return false;
-}
-
-} // namespace
-
-// Checks that a window can be created.
-TEST(MessageWindowTest, Create) {
- win::MessageWindow window;
- EXPECT_TRUE(window.Create(base::Bind(&HandleMessage)));
-}
-
-// Checks that a named window can be created.
-TEST(MessageWindowTest, CreateNamed) {
- win::MessageWindow window;
- EXPECT_TRUE(window.CreateNamed(base::Bind(&HandleMessage),
- UTF8ToUTF16("test_message_window")));
-}
-
-// Verifies that the created window can receive messages.
-TEST(MessageWindowTest, SendMessage) {
- win::MessageWindow window;
- EXPECT_TRUE(window.Create(base::Bind(&HandleMessage)));
-
- EXPECT_EQ(SendMessage(window.hwnd(), WM_USER, 100, 0), 100);
-}
-
-// Verifies that a named window can be found by name.
-TEST(MessageWindowTest, FindWindow) {
- string16 name = UTF8ToUTF16(base::GenerateGUID());
- win::MessageWindow window;
- EXPECT_TRUE(window.CreateNamed(base::Bind(&HandleMessage), name));
-
- HWND hwnd = win::MessageWindow::FindWindow(name);
- EXPECT_TRUE(hwnd != NULL);
- EXPECT_EQ(SendMessage(hwnd, WM_USER, 200, 0), 200);
-}
-
-} // namespace base
diff --git a/base/win/object_watcher_unittest.cc b/base/win/object_watcher_unittest.cc
deleted file mode 100644
index 5aa3891..0000000
--- a/base/win/object_watcher_unittest.cc
+++ /dev/null
@@ -1,221 +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/win/object_watcher.h"
-
-#include <process.h>
-
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-class QuitDelegate : public ObjectWatcher::Delegate {
- public:
- void OnObjectSignaled(HANDLE object) override {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
-};
-
-class DecrementCountDelegate : public ObjectWatcher::Delegate {
- public:
- explicit DecrementCountDelegate(int* counter) : counter_(counter) {
- }
- void OnObjectSignaled(HANDLE object) override { --(*counter_); }
-
- private:
- int* counter_;
-};
-
-void RunTest_BasicSignal(MessageLoop::Type message_loop_type) {
- MessageLoop message_loop(message_loop_type);
-
- ObjectWatcher watcher;
- EXPECT_FALSE(watcher.IsWatching());
-
- // A manual-reset event that is not yet signaled.
- HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- QuitDelegate delegate;
- bool ok = watcher.StartWatchingOnce(event, &delegate);
- EXPECT_TRUE(ok);
- EXPECT_TRUE(watcher.IsWatching());
- EXPECT_EQ(event, watcher.GetWatchedObject());
-
- SetEvent(event);
-
- RunLoop().Run();
-
- EXPECT_FALSE(watcher.IsWatching());
- CloseHandle(event);
-}
-
-void RunTest_BasicCancel(MessageLoop::Type message_loop_type) {
- MessageLoop message_loop(message_loop_type);
-
- ObjectWatcher watcher;
-
- // A manual-reset event that is not yet signaled.
- HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- QuitDelegate delegate;
- bool ok = watcher.StartWatchingOnce(event, &delegate);
- EXPECT_TRUE(ok);
-
- watcher.StopWatching();
-
- CloseHandle(event);
-}
-
-void RunTest_CancelAfterSet(MessageLoop::Type message_loop_type) {
- MessageLoop message_loop(message_loop_type);
-
- ObjectWatcher watcher;
-
- int counter = 1;
- DecrementCountDelegate delegate(&counter);
-
- // A manual-reset event that is not yet signaled.
- HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL);
-
- bool ok = watcher.StartWatchingOnce(event, &delegate);
- EXPECT_TRUE(ok);
-
- SetEvent(event);
-
- // Let the background thread do its business
- Sleep(30);
-
- watcher.StopWatching();
-
- RunLoop().RunUntilIdle();
-
- // Our delegate should not have fired.
- EXPECT_EQ(1, counter);
-
- CloseHandle(event);
-}
-
-void RunTest_SignalBeforeWatch(MessageLoop::Type message_loop_type) {
- MessageLoop message_loop(message_loop_type);
-
- ObjectWatcher watcher;
-
- // A manual-reset event that is signaled before we begin watching.
- HANDLE event = CreateEvent(NULL, TRUE, TRUE, NULL);
-
- QuitDelegate delegate;
- bool ok = watcher.StartWatchingOnce(event, &delegate);
- EXPECT_TRUE(ok);
-
- RunLoop().Run();
-
- EXPECT_FALSE(watcher.IsWatching());
- CloseHandle(event);
-}
-
-void RunTest_OutlivesMessageLoop(MessageLoop::Type message_loop_type) {
- // Simulate a MessageLoop that dies before an ObjectWatcher. This ordinarily
- // doesn't happen when people use the Thread class, but it can happen when
- // people use the Singleton pattern or atexit.
- HANDLE event = CreateEvent(NULL, TRUE, FALSE, NULL); // not signaled
- {
- ObjectWatcher watcher;
- {
- MessageLoop message_loop(message_loop_type);
-
- QuitDelegate delegate;
- watcher.StartWatchingOnce(event, &delegate);
- }
- }
- CloseHandle(event);
-}
-
-class QuitAfterMultipleDelegate : public ObjectWatcher::Delegate {
- public:
- QuitAfterMultipleDelegate(HANDLE event, int iterations)
- : event_(event), iterations_(iterations) {}
- void OnObjectSignaled(HANDLE object) override {
- if (--iterations_) {
- SetEvent(event_);
- } else {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- }
- }
-
- private:
- HANDLE event_;
- int iterations_;
-};
-
-void RunTest_ExecuteMultipleTimes(MessageLoop::Type message_loop_type) {
- MessageLoop message_loop(message_loop_type);
-
- ObjectWatcher watcher;
- EXPECT_FALSE(watcher.IsWatching());
-
- // An auto-reset event that is not yet signaled.
- HANDLE event = CreateEvent(NULL, FALSE, FALSE, NULL);
-
- QuitAfterMultipleDelegate delegate(event, 2);
- bool ok = watcher.StartWatchingMultipleTimes(event, &delegate);
- EXPECT_TRUE(ok);
- EXPECT_TRUE(watcher.IsWatching());
- EXPECT_EQ(event, watcher.GetWatchedObject());
-
- SetEvent(event);
-
- RunLoop().Run();
-
- EXPECT_TRUE(watcher.IsWatching());
- EXPECT_TRUE(watcher.StopWatching());
- CloseHandle(event);
-}
-
-} // namespace
-
-//-----------------------------------------------------------------------------
-
-TEST(ObjectWatcherTest, BasicSignal) {
- RunTest_BasicSignal(MessageLoop::TYPE_DEFAULT);
- RunTest_BasicSignal(MessageLoop::TYPE_IO);
- RunTest_BasicSignal(MessageLoop::TYPE_UI);
-}
-
-TEST(ObjectWatcherTest, BasicCancel) {
- RunTest_BasicCancel(MessageLoop::TYPE_DEFAULT);
- RunTest_BasicCancel(MessageLoop::TYPE_IO);
- RunTest_BasicCancel(MessageLoop::TYPE_UI);
-}
-
-TEST(ObjectWatcherTest, CancelAfterSet) {
- RunTest_CancelAfterSet(MessageLoop::TYPE_DEFAULT);
- RunTest_CancelAfterSet(MessageLoop::TYPE_IO);
- RunTest_CancelAfterSet(MessageLoop::TYPE_UI);
-}
-
-TEST(ObjectWatcherTest, SignalBeforeWatch) {
- RunTest_SignalBeforeWatch(MessageLoop::TYPE_DEFAULT);
- RunTest_SignalBeforeWatch(MessageLoop::TYPE_IO);
- RunTest_SignalBeforeWatch(MessageLoop::TYPE_UI);
-}
-
-TEST(ObjectWatcherTest, OutlivesMessageLoop) {
- RunTest_OutlivesMessageLoop(MessageLoop::TYPE_DEFAULT);
- RunTest_OutlivesMessageLoop(MessageLoop::TYPE_IO);
- RunTest_OutlivesMessageLoop(MessageLoop::TYPE_UI);
-}
-
-TEST(ObjectWatcherTest, ExecuteMultipleTimes) {
- RunTest_ExecuteMultipleTimes(MessageLoop::TYPE_DEFAULT);
- RunTest_ExecuteMultipleTimes(MessageLoop::TYPE_IO);
- RunTest_ExecuteMultipleTimes(MessageLoop::TYPE_UI);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/pe_image_unittest.cc b/base/win/pe_image_unittest.cc
deleted file mode 100644
index 2216449..0000000
--- a/base/win/pe_image_unittest.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.
-
-// This file contains unit tests for PEImage.
-#include <algorithm>
-#include <vector>
-
-#include "base/files/file_path.h"
-#include "base/path_service.h"
-#include "base/scoped_native_library.h"
-#include "base/win/pe_image.h"
-#include "build_config.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-// Just counts the number of invocations.
-bool ImportsCallback(const PEImage& image,
- LPCSTR module,
- DWORD ordinal,
- LPCSTR name,
- DWORD hint,
- PIMAGE_THUNK_DATA iat,
- PVOID cookie) {
- int* count = reinterpret_cast<int*>(cookie);
- (*count)++;
- return true;
-}
-
-// Just counts the number of invocations.
-bool SectionsCallback(const PEImage& image,
- PIMAGE_SECTION_HEADER header,
- PVOID section_start,
- DWORD section_size,
- PVOID cookie) {
- int* count = reinterpret_cast<int*>(cookie);
- (*count)++;
- return true;
-}
-
-// Just counts the number of invocations.
-bool RelocsCallback(const PEImage& image,
- WORD type,
- PVOID address,
- PVOID cookie) {
- int* count = reinterpret_cast<int*>(cookie);
- (*count)++;
- return true;
-}
-
-// Just counts the number of invocations.
-bool ImportChunksCallback(const PEImage& image,
- LPCSTR module,
- PIMAGE_THUNK_DATA name_table,
- PIMAGE_THUNK_DATA iat,
- PVOID cookie) {
- int* count = reinterpret_cast<int*>(cookie);
- (*count)++;
- return true;
-}
-
-// Just counts the number of invocations.
-bool DelayImportChunksCallback(const PEImage& image,
- PImgDelayDescr delay_descriptor,
- LPCSTR module,
- PIMAGE_THUNK_DATA name_table,
- PIMAGE_THUNK_DATA iat,
- PVOID cookie) {
- int* count = reinterpret_cast<int*>(cookie);
- (*count)++;
- return true;
-}
-
-// Just counts the number of invocations.
-bool ExportsCallback(const PEImage& image,
- DWORD ordinal,
- DWORD hint,
- LPCSTR name,
- PVOID function,
- LPCSTR forward,
- PVOID cookie) {
- int* count = reinterpret_cast<int*>(cookie);
- (*count)++;
- return true;
-}
-
-} // namespace
-
-// Tests that we are able to enumerate stuff from a PE file, and that
-// the actual number of items found matches an expected value.
-TEST(PEImageTest, EnumeratesPE) {
- base::FilePath pe_image_test_path;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &pe_image_test_path));
- pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image"));
-
-#if defined(ARCH_CPU_64_BITS)
- pe_image_test_path =
- pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_64.dll"));
- const int sections = 6;
- const int imports_dlls = 2;
- const int delay_dlls = 2;
- const int exports = 3;
- const int imports = 70;
- const int delay_imports = 2;
- const int relocs = 976;
-#else
- pe_image_test_path =
- pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_32.dll"));
- const int sections = 5;
- const int imports_dlls = 2;
- const int delay_dlls = 2;
- const int exports = 3;
- const int imports = 66;
- const int delay_imports = 2;
- const int relocs = 2114;
-#endif
-
- ScopedNativeLibrary module(pe_image_test_path);
- ASSERT_TRUE(module.is_valid());
-
- PEImage pe(module.get());
- int count = 0;
- EXPECT_TRUE(pe.VerifyMagic());
-
- pe.EnumSections(SectionsCallback, &count);
- EXPECT_EQ(sections, count);
-
- count = 0;
- pe.EnumImportChunks(ImportChunksCallback, &count);
- EXPECT_EQ(imports_dlls, count);
-
- count = 0;
- pe.EnumDelayImportChunks(DelayImportChunksCallback, &count);
- EXPECT_EQ(delay_dlls, count);
-
- count = 0;
- pe.EnumExports(ExportsCallback, &count);
- EXPECT_EQ(exports, count);
-
- count = 0;
- pe.EnumAllImports(ImportsCallback, &count);
- EXPECT_EQ(imports, count);
-
- count = 0;
- pe.EnumAllDelayImports(ImportsCallback, &count);
- EXPECT_EQ(delay_imports, count);
-
- count = 0;
- pe.EnumRelocs(RelocsCallback, &count);
- EXPECT_EQ(relocs, count);
-}
-
-// Tests that we can locate an specific exported symbol, by name and by ordinal.
-TEST(PEImageTest, RetrievesExports) {
- ScopedNativeLibrary module(FilePath(L"advapi32.dll"));
- ASSERT_TRUE(module.is_valid());
-
- PEImage pe(module.get());
- WORD ordinal;
-
- EXPECT_TRUE(pe.GetProcOrdinal("RegEnumKeyExW", &ordinal));
-
- FARPROC address1 = pe.GetProcAddress("RegEnumKeyExW");
- FARPROC address2 = pe.GetProcAddress(reinterpret_cast<char*>(ordinal));
- EXPECT_TRUE(address1 != NULL);
- EXPECT_TRUE(address2 != NULL);
- EXPECT_TRUE(address1 == address2);
-}
-
-// Tests that we can locate a forwarded export.
-TEST(PEImageTest, ForwardedExport) {
- base::FilePath pe_image_test_path;
- ASSERT_TRUE(PathService::Get(DIR_TEST_DATA, &pe_image_test_path));
- pe_image_test_path = pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image"));
-
-#if defined(ARCH_CPU_64_BITS)
- pe_image_test_path =
- pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_64.dll"));
-#else
- pe_image_test_path =
- pe_image_test_path.Append(FILE_PATH_LITERAL("pe_image_test_32.dll"));
-#endif
-
- ScopedNativeLibrary module(pe_image_test_path);
-
- ASSERT_TRUE(module.is_valid());
-
- PEImage pe(module.get());
-
- FARPROC addr = pe.GetProcAddress("FwdExport");
- EXPECT_EQ(FARPROC(-1), addr);
-
- PDWORD export_entry = pe.GetExportEntry("FwdExport");
- EXPECT_NE(nullptr, export_entry);
- PVOID fwd_addr = pe.RVAToAddr(*export_entry);
- const char expected_fwd[] = "KERNEL32.CreateFileA";
- EXPECT_STREQ(expected_fwd, reinterpret_cast<char*>(fwd_addr));
-}
-
-// Test that we can get debug id out of a module.
-TEST(PEImageTest, GetDebugId) {
- ScopedNativeLibrary module(FilePath(L"advapi32.dll"));
- ASSERT_TRUE(module.is_valid());
-
- PEImage pe(module.get());
- GUID guid = {0};
- DWORD age = 0;
- LPCSTR pdb_file = nullptr;
- EXPECT_TRUE(pe.GetDebugId(&guid, &age, &pdb_file));
- EXPECT_STREQ("advapi32.pdb", pdb_file);
-
- // Should be valid to call without parameters.
- EXPECT_TRUE(pe.GetDebugId(nullptr, nullptr, nullptr));
-
- GUID empty_guid = {0};
- EXPECT_TRUE(!IsEqualGUID(empty_guid, guid));
- EXPECT_NE(0U, age);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/registry_unittest.cc b/base/win/registry_unittest.cc
deleted file mode 100644
index 5a18ffa..0000000
--- a/base/win/registry_unittest.cc
+++ /dev/null
@@ -1,423 +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/win/registry.h"
-
-#include <stdint.h>
-
-#include <cstring>
-#include <vector>
-
-#include "base/bind.h"
-#include "base/compiler_specific.h"
-#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
-#include "base/run_loop.h"
-#include "base/stl_util.h"
-#include "base/win/windows_version.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-class RegistryTest : public testing::Test {
- protected:
-#if defined(_WIN64)
- static const REGSAM kNativeViewMask = KEY_WOW64_64KEY;
- static const REGSAM kRedirectedViewMask = KEY_WOW64_32KEY;
-#else
- static const REGSAM kNativeViewMask = KEY_WOW64_32KEY;
- static const REGSAM kRedirectedViewMask = KEY_WOW64_64KEY;
-#endif // _WIN64
-
- RegistryTest() {}
- void SetUp() override {
- // Create a temporary key.
- RegKey key(HKEY_CURRENT_USER, L"", KEY_ALL_ACCESS);
- key.DeleteKey(kRootKey);
- ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, kRootKey, KEY_READ));
- foo_software_key_ = L"Software\\";
- foo_software_key_ += kRootKey;
- foo_software_key_ += L"\\Foo";
- }
-
- void TearDown() override {
- // Clean up the temporary key.
- RegKey key(HKEY_CURRENT_USER, L"", KEY_SET_VALUE);
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
- ASSERT_NE(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
- }
-
- static bool IsRedirectorPresent() {
-#if defined(_WIN64)
- return true;
-#else
- return OSInfo::GetInstance()->wow64_status() == OSInfo::WOW64_ENABLED;
-#endif
- }
-
- const wchar_t* const kRootKey = L"Base_Registry_Unittest";
- std::wstring foo_software_key_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(RegistryTest);
-};
-
-// static
-const REGSAM RegistryTest::kNativeViewMask;
-const REGSAM RegistryTest::kRedirectedViewMask;
-
-TEST_F(RegistryTest, ValueTest) {
- RegKey key;
-
- std::wstring foo_key(kRootKey);
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ));
-
- {
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ | KEY_SET_VALUE));
- ASSERT_TRUE(key.Valid());
-
- const wchar_t kStringValueName[] = L"StringValue";
- const wchar_t kDWORDValueName[] = L"DWORDValue";
- const wchar_t kInt64ValueName[] = L"Int64Value";
- const wchar_t kStringData[] = L"string data";
- const DWORD kDWORDData = 0xdeadbabe;
- const int64_t kInt64Data = 0xdeadbabedeadbabeLL;
-
- // Test value creation
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kStringValueName, kStringData));
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kDWORDValueName, kDWORDData));
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kInt64ValueName, &kInt64Data,
- sizeof(kInt64Data), REG_QWORD));
- EXPECT_EQ(3U, key.GetValueCount());
- EXPECT_TRUE(key.HasValue(kStringValueName));
- EXPECT_TRUE(key.HasValue(kDWORDValueName));
- EXPECT_TRUE(key.HasValue(kInt64ValueName));
-
- // Test Read
- std::wstring string_value;
- DWORD dword_value = 0;
- int64_t int64_value = 0;
- ASSERT_EQ(ERROR_SUCCESS, key.ReadValue(kStringValueName, &string_value));
- ASSERT_EQ(ERROR_SUCCESS, key.ReadValueDW(kDWORDValueName, &dword_value));
- ASSERT_EQ(ERROR_SUCCESS, key.ReadInt64(kInt64ValueName, &int64_value));
- EXPECT_STREQ(kStringData, string_value.c_str());
- EXPECT_EQ(kDWORDData, dword_value);
- EXPECT_EQ(kInt64Data, int64_value);
-
- // Make sure out args are not touched if ReadValue fails
- const wchar_t* kNonExistent = L"NonExistent";
- ASSERT_NE(ERROR_SUCCESS, key.ReadValue(kNonExistent, &string_value));
- ASSERT_NE(ERROR_SUCCESS, key.ReadValueDW(kNonExistent, &dword_value));
- ASSERT_NE(ERROR_SUCCESS, key.ReadInt64(kNonExistent, &int64_value));
- EXPECT_STREQ(kStringData, string_value.c_str());
- EXPECT_EQ(kDWORDData, dword_value);
- EXPECT_EQ(kInt64Data, int64_value);
-
- // Test delete
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kStringValueName));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kDWORDValueName));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteValue(kInt64ValueName));
- EXPECT_EQ(0U, key.GetValueCount());
- EXPECT_FALSE(key.HasValue(kStringValueName));
- EXPECT_FALSE(key.HasValue(kDWORDValueName));
- EXPECT_FALSE(key.HasValue(kInt64ValueName));
- }
-}
-
-TEST_F(RegistryTest, BigValueIteratorTest) {
- RegKey key;
- std::wstring foo_key(kRootKey);
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ | KEY_SET_VALUE));
- ASSERT_TRUE(key.Valid());
-
- // Create a test value that is larger than MAX_PATH.
- std::wstring data(MAX_PATH * 2, L'a');
-
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(data.c_str(), data.c_str()));
-
- RegistryValueIterator iterator(HKEY_CURRENT_USER, foo_key.c_str());
- ASSERT_TRUE(iterator.Valid());
- EXPECT_STREQ(data.c_str(), iterator.Name());
- EXPECT_STREQ(data.c_str(), iterator.Value());
- // ValueSize() is in bytes, including NUL.
- EXPECT_EQ((MAX_PATH * 2 + 1) * sizeof(wchar_t), iterator.ValueSize());
- ++iterator;
- EXPECT_FALSE(iterator.Valid());
-}
-
-TEST_F(RegistryTest, TruncatedCharTest) {
- RegKey key;
- std::wstring foo_key(kRootKey);
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ | KEY_SET_VALUE));
- ASSERT_TRUE(key.Valid());
-
- const wchar_t kName[] = L"name";
- // kData size is not a multiple of sizeof(wchar_t).
- const uint8_t kData[] = {1, 2, 3, 4, 5};
- EXPECT_EQ(5u, arraysize(kData));
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(kName, kData,
- arraysize(kData), REG_BINARY));
-
- RegistryValueIterator iterator(HKEY_CURRENT_USER, foo_key.c_str());
- ASSERT_TRUE(iterator.Valid());
- EXPECT_STREQ(kName, iterator.Name());
- // ValueSize() is in bytes.
- ASSERT_EQ(arraysize(kData), iterator.ValueSize());
- // Value() is NUL terminated.
- int end = (iterator.ValueSize() + sizeof(wchar_t) - 1) / sizeof(wchar_t);
- EXPECT_NE(L'\0', iterator.Value()[end-1]);
- EXPECT_EQ(L'\0', iterator.Value()[end]);
- EXPECT_EQ(0, std::memcmp(kData, iterator.Value(), arraysize(kData)));
- ++iterator;
- EXPECT_FALSE(iterator.Valid());
-}
-
-TEST_F(RegistryTest, RecursiveDelete) {
- RegKey key;
- // Create kRootKey->Foo
- // \->Bar (TestValue)
- // \->Foo (TestValue)
- // \->Bar
- // \->Foo
- // \->Moo
- // \->Foo
- // and delete kRootKey->Foo
- std::wstring foo_key(kRootKey);
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Moo", KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
- foo_key += L"\\Bar";
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.WriteValue(L"TestValue", L"TestData"));
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
-
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Bar"));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo"));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar\\Foo"));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Bar"));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteEmptyKey(L"Foo\\Foo"));
-
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Bar", KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"Foo", KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L""));
- ASSERT_NE(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
-
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(L"Foo"));
- ASSERT_NE(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
-}
-
-// This test requires running as an Administrator as it tests redirected
-// registry writes to HKLM\Software
-// http://msdn.microsoft.com/en-us/library/windows/desktop/aa384253.aspx
-// TODO(wfh): flaky test on Vista. See http://crbug.com/377917
-TEST_F(RegistryTest, DISABLED_Wow64RedirectedFromNative) {
- if (!IsRedirectorPresent())
- return;
-
- RegKey key;
-
- // Test redirected key access from non-redirected.
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_LOCAL_MACHINE,
- foo_software_key_.c_str(),
- KEY_WRITE | kRedirectedViewMask));
- ASSERT_NE(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
- ASSERT_NE(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- foo_software_key_.c_str(),
- KEY_READ | kNativeViewMask));
-
- // Open the non-redirected view of the parent and try to delete the test key.
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE, L"Software", KEY_SET_VALUE));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- L"Software",
- KEY_SET_VALUE | kNativeViewMask));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
-
- // Open the redirected view and delete the key created above.
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- L"Software",
- KEY_SET_VALUE | kRedirectedViewMask));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
-}
-
-// Test for the issue found in http://crbug.com/384587 where OpenKey would call
-// Close() and reset wow64_access_ flag to 0 and cause a NOTREACHED to hit on a
-// subsequent OpenKey call.
-TEST_F(RegistryTest, SameWowFlags) {
- RegKey key;
-
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- L"Software",
- KEY_READ | KEY_WOW64_64KEY));
- ASSERT_EQ(ERROR_SUCCESS,
- key.OpenKey(L"Microsoft",
- KEY_READ | KEY_WOW64_64KEY));
- ASSERT_EQ(ERROR_SUCCESS,
- key.OpenKey(L"Windows",
- KEY_READ | KEY_WOW64_64KEY));
-}
-
-// TODO(wfh): flaky test on Vista. See http://crbug.com/377917
-TEST_F(RegistryTest, DISABLED_Wow64NativeFromRedirected) {
- if (!IsRedirectorPresent())
- return;
- RegKey key;
-
- // Test non-redirected key access from redirected.
- ASSERT_EQ(ERROR_SUCCESS,
- key.Create(HKEY_LOCAL_MACHINE,
- foo_software_key_.c_str(),
- KEY_WRITE | kNativeViewMask));
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE, foo_software_key_.c_str(), KEY_READ));
- ASSERT_NE(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- foo_software_key_.c_str(),
- KEY_READ | kRedirectedViewMask));
-
- // Open the redirected view of the parent and try to delete the test key
- // from the non-redirected view.
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- L"Software",
- KEY_SET_VALUE | kRedirectedViewMask));
- ASSERT_NE(ERROR_SUCCESS, key.DeleteKey(kRootKey));
-
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_LOCAL_MACHINE,
- L"Software",
- KEY_SET_VALUE | kNativeViewMask));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(kRootKey));
-}
-
-TEST_F(RegistryTest, OpenSubKey) {
- RegKey key;
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER,
- kRootKey,
- KEY_READ | KEY_CREATE_SUB_KEY));
-
- ASSERT_NE(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS, key.CreateKey(L"foo", KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_READ));
- ASSERT_EQ(ERROR_SUCCESS, key.OpenKey(L"foo", KEY_READ));
-
- std::wstring foo_key(kRootKey);
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS,
- key.Open(HKEY_CURRENT_USER, foo_key.c_str(), KEY_READ));
-
- ASSERT_EQ(ERROR_SUCCESS, key.Open(HKEY_CURRENT_USER, kRootKey, KEY_WRITE));
- ASSERT_EQ(ERROR_SUCCESS, key.DeleteKey(L"foo"));
-}
-
-class TestChangeDelegate {
- public:
- TestChangeDelegate() : called_(false) {}
- ~TestChangeDelegate() {}
-
- void OnKeyChanged() {
- RunLoop::QuitCurrentWhenIdleDeprecated();
- called_ = true;
- }
-
- bool WasCalled() {
- bool was_called = called_;
- called_ = false;
- return was_called;
- }
-
- private:
- bool called_;
-};
-
-TEST_F(RegistryTest, ChangeCallback) {
- RegKey key;
- TestChangeDelegate delegate;
- MessageLoop message_loop;
-
- std::wstring foo_key(kRootKey);
- foo_key += L"\\Foo";
- ASSERT_EQ(ERROR_SUCCESS, key.Create(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ));
-
- ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
- Unretained(&delegate))));
- EXPECT_FALSE(delegate.WasCalled());
-
- // Make some change.
- RegKey key2;
- ASSERT_EQ(ERROR_SUCCESS, key2.Open(HKEY_CURRENT_USER, foo_key.c_str(),
- KEY_READ | KEY_SET_VALUE));
- ASSERT_TRUE(key2.Valid());
- EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name", L"data"));
-
- // Allow delivery of the notification.
- EXPECT_FALSE(delegate.WasCalled());
- base::RunLoop().Run();
-
- ASSERT_TRUE(delegate.WasCalled());
- EXPECT_FALSE(delegate.WasCalled());
-
- ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
- Unretained(&delegate))));
-
- // Change something else.
- EXPECT_EQ(ERROR_SUCCESS, key2.WriteValue(L"name2", L"data2"));
- base::RunLoop().Run();
- ASSERT_TRUE(delegate.WasCalled());
-
- ASSERT_TRUE(key.StartWatching(Bind(&TestChangeDelegate::OnKeyChanged,
- Unretained(&delegate))));
- base::RunLoop().RunUntilIdle();
- EXPECT_FALSE(delegate.WasCalled());
-}
-
-} // namespace
-
-} // namespace win
-} // namespace base
diff --git a/base/win/scoped_bstr_unittest.cc b/base/win/scoped_bstr_unittest.cc
deleted file mode 100644
index d305e5a..0000000
--- a/base/win/scoped_bstr_unittest.cc
+++ /dev/null
@@ -1,80 +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 <stddef.h>
-
-#include "base/macros.h"
-#include "base/win/scoped_bstr.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-static const wchar_t kTestString1[] = L"123";
-static const wchar_t kTestString2[] = L"456789";
-size_t test1_len = arraysize(kTestString1) - 1;
-size_t test2_len = arraysize(kTestString2) - 1;
-
-void DumbBstrTests() {
- ScopedBstr b;
- EXPECT_TRUE(b == NULL);
- EXPECT_EQ(0u, b.Length());
- EXPECT_EQ(0u, b.ByteLength());
- b.Reset(NULL);
- EXPECT_TRUE(b == NULL);
- EXPECT_TRUE(b.Release() == NULL);
- ScopedBstr b2;
- b.Swap(b2);
- EXPECT_TRUE(b2 == NULL);
-}
-
-void GiveMeABstr(BSTR* ret) {
- *ret = SysAllocString(kTestString1);
-}
-
-void BasicBstrTests() {
- ScopedBstr b1(kTestString1);
- EXPECT_EQ(test1_len, b1.Length());
- EXPECT_EQ(test1_len * sizeof(kTestString1[0]), b1.ByteLength());
-
- ScopedBstr b2;
- b1.Swap(b2);
- EXPECT_EQ(test1_len, b2.Length());
- EXPECT_EQ(0u, b1.Length());
- EXPECT_EQ(0, lstrcmp(b2, kTestString1));
- BSTR tmp = b2.Release();
- EXPECT_TRUE(tmp != NULL);
- EXPECT_EQ(0, lstrcmp(tmp, kTestString1));
- EXPECT_TRUE(b2 == NULL);
- SysFreeString(tmp);
-
- GiveMeABstr(b2.Receive());
- EXPECT_TRUE(b2 != NULL);
- b2.Reset();
- EXPECT_TRUE(b2.AllocateBytes(100) != NULL);
- EXPECT_EQ(100u, b2.ByteLength());
- EXPECT_EQ(100 / sizeof(kTestString1[0]), b2.Length());
- lstrcpy(static_cast<BSTR>(b2), kTestString1);
- EXPECT_EQ(test1_len, static_cast<size_t>(lstrlen(b2)));
- EXPECT_EQ(100 / sizeof(kTestString1[0]), b2.Length());
- b2.SetByteLen(lstrlen(b2) * sizeof(kTestString2[0]));
- EXPECT_EQ(b2.Length(), static_cast<size_t>(lstrlen(b2)));
-
- EXPECT_TRUE(b1.Allocate(kTestString2) != NULL);
- EXPECT_EQ(test2_len, b1.Length());
- b1.SetByteLen((test2_len - 1) * sizeof(kTestString2[0]));
- EXPECT_EQ(test2_len - 1, b1.Length());
-}
-
-} // namespace
-
-TEST(ScopedBstrTest, ScopedBstr) {
- DumbBstrTests();
- BasicBstrTests();
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/scoped_handle_unittest.cc b/base/win/scoped_handle_unittest.cc
deleted file mode 100644
index ca6fb45..0000000
--- a/base/win/scoped_handle_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 <windows.h>
-#include <winternl.h>
-
-#include "base/base_switches.h"
-#include "base/command_line.h"
-#include "base/files/file_path.h"
-#include "base/scoped_native_library.h"
-#include "base/test/multiprocess_test.h"
-#include "base/test/test_timeouts.h"
-#include "base/win/scoped_handle.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-namespace win {
-
-namespace testing {
-extern "C" bool __declspec(dllexport) RunTest();
-} // namespace testing
-
-TEST(ScopedHandleTest, ScopedHandle) {
- // Any illegal error code will do. We just need to test that it is preserved
- // by ScopedHandle to avoid bug 528394.
- const DWORD magic_error = 0x12345678;
-
- HANDLE handle = ::CreateMutex(nullptr, false, nullptr);
- // Call SetLastError after creating the handle.
- ::SetLastError(magic_error);
- base::win::ScopedHandle handle_holder(handle);
- EXPECT_EQ(magic_error, ::GetLastError());
-
- // Create a new handle and then set LastError again.
- handle = ::CreateMutex(nullptr, false, nullptr);
- ::SetLastError(magic_error);
- handle_holder.Set(handle);
- EXPECT_EQ(magic_error, ::GetLastError());
-
- // Create a new handle and then set LastError again.
- handle = ::CreateMutex(nullptr, false, nullptr);
- base::win::ScopedHandle handle_source(handle);
- ::SetLastError(magic_error);
- handle_holder = std::move(handle_source);
- EXPECT_EQ(magic_error, ::GetLastError());
-}
-
-TEST(ScopedHandleTest, ActiveVerifierTrackedHasBeenClosed) {
- HANDLE handle = ::CreateMutex(nullptr, false, nullptr);
- ASSERT_NE(HANDLE(nullptr), handle);
- typedef NTSTATUS(WINAPI * NtCloseFunc)(HANDLE);
- NtCloseFunc ntclose = reinterpret_cast<NtCloseFunc>(
- GetProcAddress(GetModuleHandle(L"ntdll.dll"), "NtClose"));
- ASSERT_NE(nullptr, ntclose);
-
- ASSERT_DEATH({
- base::win::ScopedHandle handle_holder(handle);
- ntclose(handle);
- // Destructing a ScopedHandle with an illegally closed handle should fail.
- }, "");
-}
-
-TEST(ScopedHandleTest, ActiveVerifierDoubleTracking) {
- HANDLE handle = ::CreateMutex(nullptr, false, nullptr);
- ASSERT_NE(HANDLE(nullptr), handle);
-
- base::win::ScopedHandle handle_holder(handle);
-
- ASSERT_DEATH({
- base::win::ScopedHandle handle_holder2(handle);
- }, "");
-}
-
-TEST(ScopedHandleTest, ActiveVerifierWrongOwner) {
- HANDLE handle = ::CreateMutex(nullptr, false, nullptr);
- ASSERT_NE(HANDLE(nullptr), handle);
-
- base::win::ScopedHandle handle_holder(handle);
- ASSERT_DEATH({
- base::win::ScopedHandle handle_holder2;
- handle_holder2.handle_ = handle;
- }, "");
- ASSERT_TRUE(handle_holder.IsValid());
- handle_holder.Close();
-}
-
-TEST(ScopedHandleTest, ActiveVerifierUntrackedHandle) {
- HANDLE handle = ::CreateMutex(nullptr, false, nullptr);
- ASSERT_NE(HANDLE(nullptr), handle);
-
- ASSERT_DEATH({
- base::win::ScopedHandle handle_holder;
- handle_holder.handle_ = handle;
- }, "");
-
- ASSERT_TRUE(::CloseHandle(handle));
-}
-
-// Under ASan, the multi-process test crashes during process shutdown for
-// unknown reasons. Disable it for now. http://crbug.com/685262
-#if defined(ADDRESS_SANITIZER)
-#define MAYBE_MultiProcess DISABLED_MultiProcess
-#else
-#define MAYBE_MultiProcess MultiProcess
-#endif
-
-TEST(ScopedHandleTest, MAYBE_MultiProcess) {
- // Initializing ICU in the child process causes a scoped handle to be created
- // before the test gets a chance to test the race condition, so disable ICU
- // for the child process here.
- CommandLine command_line(base::GetMultiProcessTestChildBaseCommandLine());
- command_line.AppendSwitch(switches::kTestDoNotInitializeIcu);
-
- base::Process test_child_process = base::SpawnMultiProcessTestChild(
- "ActiveVerifierChildProcess", command_line, LaunchOptions());
-
- int rv = -1;
- ASSERT_TRUE(test_child_process.WaitForExitWithTimeout(
- TestTimeouts::action_timeout(), &rv));
- EXPECT_EQ(0, rv);
-}
-
-MULTIPROCESS_TEST_MAIN(ActiveVerifierChildProcess) {
- ScopedNativeLibrary module(FilePath(L"scoped_handle_test_dll.dll"));
-
- if (!module.is_valid())
- return 1;
- auto run_test_function = reinterpret_cast<decltype(&testing::RunTest)>(
- module.GetFunctionPointer("RunTest"));
- if (!run_test_function)
- return 1;
- if (!run_test_function())
- return 1;
-
- return 0;
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/scoped_hstring_unittest.cc b/base/win/scoped_hstring_unittest.cc
deleted file mode 100644
index fdcf8ff..0000000
--- a/base/win/scoped_hstring_unittest.cc
+++ /dev/null
@@ -1,55 +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/win/scoped_hstring.h"
-
-#include <winstring.h>
-
-#include "base/strings/utf_string_conversions.h"
-#include "base/win/core_winrt_util.h"
-#include "base/win/windows_version.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-constexpr wchar_t kTestString1[] = L"123";
-constexpr wchar_t kTestString2[] = L"456789";
-
-} // namespace
-
-TEST(ScopedHStringTest, Init) {
- // ScopedHString requires WinRT core functions, which are not available in
- // older versions.
- if (GetVersion() < VERSION_WIN8) {
- EXPECT_FALSE(ScopedHString::ResolveCoreWinRTStringDelayload());
- return;
- }
-
- EXPECT_TRUE(ScopedHString::ResolveCoreWinRTStringDelayload());
-
- ScopedHString hstring = ScopedHString::Create(kTestString1);
- std::string buffer = hstring.GetAsUTF8();
- EXPECT_EQ(kTestString1, base::UTF8ToWide(buffer));
- base::StringPiece16 contents = hstring.Get();
- EXPECT_EQ(kTestString1, contents);
-
- hstring.reset();
- EXPECT_TRUE(hstring == NULL);
- EXPECT_EQ(NULL, hstring.get());
-
- ScopedHString hstring2 = ScopedHString::Create(kTestString2);
- hstring.swap(hstring2);
- EXPECT_TRUE(hstring2 == NULL);
-
- buffer = hstring.GetAsUTF8();
- EXPECT_EQ(kTestString2, base::UTF8ToWide(buffer));
- contents = hstring.Get();
- EXPECT_EQ(kTestString2, contents);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/scoped_process_information_unittest.cc b/base/win/scoped_process_information_unittest.cc
deleted file mode 100644
index 799b273..0000000
--- a/base/win/scoped_process_information_unittest.cc
+++ /dev/null
@@ -1,166 +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 <windows.h>
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/process/kill.h"
-#include "base/process/process.h"
-#include "base/test/multiprocess_test.h"
-#include "base/win/scoped_process_information.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace {
-
-const DWORD kProcessId = 4321;
-const DWORD kThreadId = 1234;
-const HANDLE kProcessHandle = reinterpret_cast<HANDLE>(7651);
-const HANDLE kThreadHandle = reinterpret_cast<HANDLE>(1567);
-
-void MockCreateProcess(base::win::ScopedProcessInformation* process_info) {
- PROCESS_INFORMATION process_information = {};
- process_information.dwProcessId = kProcessId;
- process_information.dwThreadId = kThreadId;
- process_information.hProcess = kProcessHandle;
- process_information.hThread = kThreadHandle;
- process_info->Set(process_information);
-}
-
-} // namespace
-
-class ScopedProcessInformationTest : public base::MultiProcessTest {
- protected:
- void DoCreateProcess(const std::string& main_id,
- PROCESS_INFORMATION* process_handle);
-};
-
-MULTIPROCESS_TEST_MAIN(ReturnSeven) {
- return 7;
-}
-
-MULTIPROCESS_TEST_MAIN(ReturnNine) {
- return 9;
-}
-
-void ScopedProcessInformationTest::DoCreateProcess(
- const std::string& main_id, PROCESS_INFORMATION* process_handle) {
- std::wstring cmd_line = MakeCmdLine(main_id).GetCommandLineString();
- STARTUPINFO startup_info = {};
- startup_info.cb = sizeof(startup_info);
-
- EXPECT_TRUE(::CreateProcess(NULL, &cmd_line[0],
- NULL, NULL, false, 0, NULL, NULL,
- &startup_info, process_handle));
-}
-
-TEST_F(ScopedProcessInformationTest, InitiallyInvalid) {
- base::win::ScopedProcessInformation process_info;
- ASSERT_FALSE(process_info.IsValid());
-}
-
-TEST_F(ScopedProcessInformationTest, Receive) {
- base::win::ScopedProcessInformation process_info;
- MockCreateProcess(&process_info);
-
- EXPECT_TRUE(process_info.IsValid());
- EXPECT_EQ(kProcessId, process_info.process_id());
- EXPECT_EQ(kThreadId, process_info.thread_id());
- EXPECT_EQ(kProcessHandle, process_info.process_handle());
- EXPECT_EQ(kThreadHandle, process_info.thread_handle());
- process_info.Take();
-}
-
-TEST_F(ScopedProcessInformationTest, TakeProcess) {
- base::win::ScopedProcessInformation process_info;
- MockCreateProcess(&process_info);
-
- HANDLE process = process_info.TakeProcessHandle();
- EXPECT_EQ(kProcessHandle, process);
- EXPECT_EQ(NULL, process_info.process_handle());
- EXPECT_EQ(0u, process_info.process_id());
- EXPECT_TRUE(process_info.IsValid());
- process_info.Take();
-}
-
-TEST_F(ScopedProcessInformationTest, TakeThread) {
- base::win::ScopedProcessInformation process_info;
- MockCreateProcess(&process_info);
-
- HANDLE thread = process_info.TakeThreadHandle();
- EXPECT_EQ(kThreadHandle, thread);
- EXPECT_EQ(NULL, process_info.thread_handle());
- EXPECT_EQ(0u, process_info.thread_id());
- EXPECT_TRUE(process_info.IsValid());
- process_info.Take();
-}
-
-TEST_F(ScopedProcessInformationTest, TakeBoth) {
- base::win::ScopedProcessInformation process_info;
- MockCreateProcess(&process_info);
-
- process_info.TakeProcessHandle();
- process_info.TakeThreadHandle();
- EXPECT_FALSE(process_info.IsValid());
- process_info.Take();
-}
-
-TEST_F(ScopedProcessInformationTest, TakeWholeStruct) {
- base::win::ScopedProcessInformation process_info;
- MockCreateProcess(&process_info);
-
- PROCESS_INFORMATION to_discard = process_info.Take();
- EXPECT_EQ(kProcessId, to_discard.dwProcessId);
- EXPECT_EQ(kThreadId, to_discard.dwThreadId);
- EXPECT_EQ(kProcessHandle, to_discard.hProcess);
- EXPECT_EQ(kThreadHandle, to_discard.hThread);
- EXPECT_FALSE(process_info.IsValid());
-}
-
-TEST_F(ScopedProcessInformationTest, Duplicate) {
- PROCESS_INFORMATION temp_process_information;
- DoCreateProcess("ReturnSeven", &temp_process_information);
- base::win::ScopedProcessInformation process_info;
- process_info.Set(temp_process_information);
-
- base::win::ScopedProcessInformation duplicate;
- duplicate.DuplicateFrom(process_info);
-
- ASSERT_TRUE(process_info.IsValid());
- ASSERT_NE(0u, process_info.process_id());
- ASSERT_EQ(duplicate.process_id(), process_info.process_id());
- ASSERT_NE(0u, process_info.thread_id());
- ASSERT_EQ(duplicate.thread_id(), process_info.thread_id());
-
- // Validate that we have separate handles that are good.
- int exit_code = 0;
- base::Process process(process_info.TakeProcessHandle());
- ASSERT_TRUE(process.WaitForExit(&exit_code));
- ASSERT_EQ(7, exit_code);
-
- exit_code = 0;
- base::Process dup_process(duplicate.TakeProcessHandle());
- ASSERT_TRUE(dup_process.WaitForExit(&exit_code));
- ASSERT_EQ(7, exit_code);
-
- ASSERT_TRUE(::CloseHandle(process_info.TakeThreadHandle()));
- ASSERT_TRUE(::CloseHandle(duplicate.TakeThreadHandle()));
-}
-
-TEST_F(ScopedProcessInformationTest, Set) {
- base::win::ScopedProcessInformation base_process_info;
- MockCreateProcess(&base_process_info);
-
- PROCESS_INFORMATION base_struct = base_process_info.Take();
-
- base::win::ScopedProcessInformation process_info;
- process_info.Set(base_struct);
-
- EXPECT_EQ(kProcessId, process_info.process_id());
- EXPECT_EQ(kThreadId, process_info.thread_id());
- EXPECT_EQ(kProcessHandle, process_info.process_handle());
- EXPECT_EQ(kThreadHandle, process_info.thread_handle());
- base_struct = process_info.Take();
-}
diff --git a/base/win/scoped_variant_unittest.cc b/base/win/scoped_variant_unittest.cc
deleted file mode 100644
index 7d61e28..0000000
--- a/base/win/scoped_variant_unittest.cc
+++ /dev/null
@@ -1,263 +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/win/scoped_variant.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-static const wchar_t kTestString1[] = L"Used to create BSTRs";
-static const wchar_t kTestString2[] = L"Also used to create BSTRs";
-
-void GiveMeAVariant(VARIANT* ret) {
- EXPECT_TRUE(ret != NULL);
- ret->vt = VT_BSTR;
- V_BSTR(ret) = ::SysAllocString(kTestString1);
-}
-
-// A dummy IDispatch implementation (if you can call it that).
-// The class does nothing intelligent really. Only increments a counter
-// when AddRef is called and decrements it when Release is called.
-class FakeComObject : public IDispatch {
- public:
- FakeComObject() : ref_(0) {
- }
-
- STDMETHOD_(DWORD, AddRef)() override {
- ref_++;
- return ref_;
- }
-
- STDMETHOD_(DWORD, Release)() override {
- ref_--;
- return ref_;
- }
-
- STDMETHOD(QueryInterface)(REFIID, void**) override { return E_NOTIMPL; }
-
- STDMETHOD(GetTypeInfoCount)(UINT*) override { return E_NOTIMPL; }
-
- STDMETHOD(GetTypeInfo)(UINT, LCID, ITypeInfo**) override { return E_NOTIMPL; }
-
- STDMETHOD(GetIDsOfNames)(REFIID, LPOLESTR*, UINT, LCID, DISPID*) override {
- return E_NOTIMPL;
- }
-
- STDMETHOD(Invoke)(DISPID,
- REFIID,
- LCID,
- WORD,
- DISPPARAMS*,
- VARIANT*,
- EXCEPINFO*,
- UINT*) override {
- return E_NOTIMPL;
- }
-
- // A way to check the internal reference count of the class.
- int ref_count() const {
- return ref_;
- }
-
- protected:
- int ref_;
-};
-
-} // namespace
-
-TEST(ScopedVariantTest, ScopedVariant) {
- ScopedVariant var;
- EXPECT_TRUE(var.type() == VT_EMPTY);
- // V_BSTR(var.ptr()) = NULL; <- NOTE: Assignment like that is not supported.
-
- ScopedVariant var_bstr(L"VT_BSTR");
- EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr()));
- EXPECT_TRUE(V_BSTR(var_bstr.ptr()) != NULL); // can't use EXPECT_NE for BSTR
- var_bstr.Reset();
- EXPECT_NE(VT_BSTR, V_VT(var_bstr.ptr()));
- var_bstr.Set(kTestString2);
- EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr()));
-
- VARIANT tmp = var_bstr.Release();
- EXPECT_EQ(VT_EMPTY, V_VT(var_bstr.ptr()));
- EXPECT_EQ(VT_BSTR, V_VT(&tmp));
- EXPECT_EQ(0, lstrcmp(V_BSTR(&tmp), kTestString2));
-
- var.Reset(tmp);
- EXPECT_EQ(VT_BSTR, V_VT(var.ptr()));
- EXPECT_EQ(0, lstrcmpW(V_BSTR(var.ptr()), kTestString2));
-
- var_bstr.Swap(var);
- EXPECT_EQ(VT_EMPTY, V_VT(var.ptr()));
- EXPECT_EQ(VT_BSTR, V_VT(var_bstr.ptr()));
- EXPECT_EQ(0, lstrcmpW(V_BSTR(var_bstr.ptr()), kTestString2));
- var_bstr.Reset();
-
- // Test the Compare and Copy routines.
- GiveMeAVariant(var_bstr.Receive());
- ScopedVariant var_bstr2(V_BSTR(var_bstr.ptr()));
- EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
- var_bstr2.Reset();
- EXPECT_NE(0, var_bstr.Compare(var_bstr2));
- var_bstr2.Reset(var_bstr.Copy());
- EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
- var_bstr2.Reset();
- var_bstr2.Set(V_BSTR(var_bstr.ptr()));
- EXPECT_EQ(0, var_bstr.Compare(var_bstr2));
- var_bstr2.Reset();
- var_bstr.Reset();
-
- // Test for the SetDate setter.
- SYSTEMTIME sys_time;
- ::GetSystemTime(&sys_time);
- DATE date;
- ::SystemTimeToVariantTime(&sys_time, &date);
- var.Reset();
- var.SetDate(date);
- EXPECT_EQ(VT_DATE, var.type());
- EXPECT_EQ(date, V_DATE(var.ptr()));
-
- // Simple setter tests. These do not require resetting the variant
- // after each test since the variant type is not "leakable" (i.e. doesn't
- // need to be freed explicitly).
-
- // We need static cast here since char defaults to int (!?).
- var.Set(static_cast<int8_t>('v'));
- EXPECT_EQ(VT_I1, var.type());
- EXPECT_EQ('v', V_I1(var.ptr()));
-
- var.Set(static_cast<short>(123));
- EXPECT_EQ(VT_I2, var.type());
- EXPECT_EQ(123, V_I2(var.ptr()));
-
- var.Set(static_cast<int32_t>(123));
- EXPECT_EQ(VT_I4, var.type());
- EXPECT_EQ(123, V_I4(var.ptr()));
-
- var.Set(static_cast<int64_t>(123));
- EXPECT_EQ(VT_I8, var.type());
- EXPECT_EQ(123, V_I8(var.ptr()));
-
- var.Set(static_cast<uint8_t>(123));
- EXPECT_EQ(VT_UI1, var.type());
- EXPECT_EQ(123u, V_UI1(var.ptr()));
-
- var.Set(static_cast<unsigned short>(123));
- EXPECT_EQ(VT_UI2, var.type());
- EXPECT_EQ(123u, V_UI2(var.ptr()));
-
- var.Set(static_cast<uint32_t>(123));
- EXPECT_EQ(VT_UI4, var.type());
- EXPECT_EQ(123u, V_UI4(var.ptr()));
-
- var.Set(static_cast<uint64_t>(123));
- EXPECT_EQ(VT_UI8, var.type());
- EXPECT_EQ(123u, V_UI8(var.ptr()));
-
- var.Set(123.123f);
- EXPECT_EQ(VT_R4, var.type());
- EXPECT_EQ(123.123f, V_R4(var.ptr()));
-
- var.Set(static_cast<double>(123.123));
- EXPECT_EQ(VT_R8, var.type());
- EXPECT_EQ(123.123, V_R8(var.ptr()));
-
- var.Set(true);
- EXPECT_EQ(VT_BOOL, var.type());
- EXPECT_EQ(VARIANT_TRUE, V_BOOL(var.ptr()));
- var.Set(false);
- EXPECT_EQ(VT_BOOL, var.type());
- EXPECT_EQ(VARIANT_FALSE, V_BOOL(var.ptr()));
-
- // Com interface tests
-
- var.Set(static_cast<IDispatch*>(NULL));
- EXPECT_EQ(VT_DISPATCH, var.type());
- EXPECT_EQ(NULL, V_DISPATCH(var.ptr()));
- var.Reset();
-
- var.Set(static_cast<IUnknown*>(NULL));
- EXPECT_EQ(VT_UNKNOWN, var.type());
- EXPECT_EQ(NULL, V_UNKNOWN(var.ptr()));
- var.Reset();
-
- FakeComObject faker;
- EXPECT_EQ(0, faker.ref_count());
- var.Set(static_cast<IDispatch*>(&faker));
- EXPECT_EQ(VT_DISPATCH, var.type());
- EXPECT_EQ(&faker, V_DISPATCH(var.ptr()));
- EXPECT_EQ(1, faker.ref_count());
- var.Reset();
- EXPECT_EQ(0, faker.ref_count());
-
- var.Set(static_cast<IUnknown*>(&faker));
- EXPECT_EQ(VT_UNKNOWN, var.type());
- EXPECT_EQ(&faker, V_UNKNOWN(var.ptr()));
- EXPECT_EQ(1, faker.ref_count());
- var.Reset();
- EXPECT_EQ(0, faker.ref_count());
-
- {
- ScopedVariant disp_var(&faker);
- EXPECT_EQ(VT_DISPATCH, disp_var.type());
- EXPECT_EQ(&faker, V_DISPATCH(disp_var.ptr()));
- EXPECT_EQ(1, faker.ref_count());
- }
- EXPECT_EQ(0, faker.ref_count());
-
- {
- ScopedVariant ref1(&faker);
- EXPECT_EQ(1, faker.ref_count());
- ScopedVariant ref2(static_cast<const VARIANT&>(ref1));
- EXPECT_EQ(2, faker.ref_count());
- ScopedVariant ref3;
- ref3 = static_cast<const VARIANT&>(ref2);
- EXPECT_EQ(3, faker.ref_count());
- }
- EXPECT_EQ(0, faker.ref_count());
-
- {
- ScopedVariant unk_var(static_cast<IUnknown*>(&faker));
- EXPECT_EQ(VT_UNKNOWN, unk_var.type());
- EXPECT_EQ(&faker, V_UNKNOWN(unk_var.ptr()));
- EXPECT_EQ(1, faker.ref_count());
- }
- EXPECT_EQ(0, faker.ref_count());
-
- VARIANT raw;
- raw.vt = VT_UNKNOWN;
- raw.punkVal = &faker;
- EXPECT_EQ(0, faker.ref_count());
- var.Set(raw);
- EXPECT_EQ(1, faker.ref_count());
- var.Reset();
- EXPECT_EQ(0, faker.ref_count());
-
- {
- ScopedVariant number(123);
- EXPECT_EQ(VT_I4, number.type());
- EXPECT_EQ(123, V_I4(number.ptr()));
- }
-
- // SAFEARRAY tests
- var.Set(static_cast<SAFEARRAY*>(NULL));
- EXPECT_EQ(VT_EMPTY, var.type());
-
- SAFEARRAY* sa = ::SafeArrayCreateVector(VT_UI1, 0, 100);
- ASSERT_TRUE(sa != NULL);
-
- var.Set(sa);
- EXPECT_TRUE(ScopedVariant::IsLeakableVarType(var.type()));
- EXPECT_EQ(VT_ARRAY | VT_UI1, var.type());
- EXPECT_EQ(sa, V_ARRAY(var.ptr()));
- // The array is destroyed in the destructor of var.
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/scoped_winrt_initializer_unittest.cc b/base/win/scoped_winrt_initializer_unittest.cc
deleted file mode 100644
index 9df1187..0000000
--- a/base/win/scoped_winrt_initializer_unittest.cc
+++ /dev/null
@@ -1,47 +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/win/scoped_winrt_initializer.h"
-
-#include "base/test/gtest_util.h"
-#include "base/win/com_init_util.h"
-#include "base/win/scoped_com_initializer.h"
-#include "base/win/windows_version.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-TEST(ScopedWinrtInitializer, BasicFunctionality) {
- if (GetVersion() < VERSION_WIN8)
- return;
-
- AssertComApartmentType(ComApartmentType::NONE);
- {
- ScopedWinrtInitializer scoped_winrt_initializer;
- AssertComApartmentType(ComApartmentType::MTA);
- }
- AssertComApartmentType(ComApartmentType::NONE);
-}
-
-TEST(ScopedWinrtInitializer, ApartmentChangeCheck) {
- if (GetVersion() < VERSION_WIN8)
- return;
-
- ScopedCOMInitializer com_initializer;
- // ScopedCOMInitializer initialized an STA and the following should be a
- // failed request for an MTA.
- EXPECT_DCHECK_DEATH({ ScopedWinrtInitializer scoped_winrt_initializer; });
-}
-
-TEST(ScopedWinrtInitializer, VersionCheck) {
- if (GetVersion() >= VERSION_WIN8)
- return;
-
- // ScopedWinrtInitializer is unsupported on versions prior to Windows 8.
- EXPECT_DCHECK_DEATH({ ScopedWinrtInitializer scoped_winrt_initializer; });
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/shortcut_unittest.cc b/base/win/shortcut_unittest.cc
deleted file mode 100644
index 3c1c26f..0000000
--- a/base/win/shortcut_unittest.cc
+++ /dev/null
@@ -1,330 +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/win/shortcut.h"
-
-#include <stdint.h>
-
-#include <string>
-
-#include "base/files/file_path.h"
-#include "base/files/file_util.h"
-#include "base/files/scoped_temp_dir.h"
-#include "base/macros.h"
-#include "base/test/test_file_util.h"
-#include "base/test/test_shortcut_win.h"
-#include "base/win/scoped_com_initializer.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-static const char kFileContents[] = "This is a target.";
-static const char kFileContents2[] = "This is another target.";
-
-class ShortcutTest : public testing::Test {
- protected:
- void SetUp() override {
- ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
- ASSERT_TRUE(temp_dir_2_.CreateUniqueTempDir());
-
- link_file_ = temp_dir_.GetPath().Append(L"My Link.lnk");
-
- // Shortcut 1's properties
- {
- const FilePath target_file(temp_dir_.GetPath().Append(L"Target 1.txt"));
- WriteFile(target_file, kFileContents, arraysize(kFileContents));
-
- link_properties_.set_target(target_file);
- link_properties_.set_working_dir(temp_dir_.GetPath());
- link_properties_.set_arguments(L"--magic --awesome");
- link_properties_.set_description(L"Chrome is awesome.");
- link_properties_.set_icon(link_properties_.target, 4);
- link_properties_.set_app_id(L"Chrome");
- link_properties_.set_dual_mode(false);
-
- // The CLSID below was randomly selected.
- static constexpr CLSID toast_activator_clsid = {
- 0x08d401c2,
- 0x3f79,
- 0x41d8,
- {0x89, 0xd0, 0x99, 0x25, 0xee, 0x16, 0x28, 0x63}};
- link_properties_.set_toast_activator_clsid(toast_activator_clsid);
- }
-
- // Shortcut 2's properties (all different from properties of shortcut 1).
- {
- const FilePath target_file_2(temp_dir_.GetPath().Append(L"Target 2.txt"));
- WriteFile(target_file_2, kFileContents2, arraysize(kFileContents2));
-
- FilePath icon_path_2;
- CreateTemporaryFileInDir(temp_dir_.GetPath(), &icon_path_2);
-
- link_properties_2_.set_target(target_file_2);
- link_properties_2_.set_working_dir(temp_dir_2_.GetPath());
- link_properties_2_.set_arguments(L"--super --crazy");
- link_properties_2_.set_description(L"The best in the west.");
- link_properties_2_.set_icon(icon_path_2, 0);
- link_properties_2_.set_app_id(L"Chrome.UserLevelCrazySuffix");
- link_properties_2_.set_dual_mode(true);
- link_properties_2_.set_toast_activator_clsid(CLSID_NULL);
- }
- }
-
- ScopedCOMInitializer com_initializer_;
- ScopedTempDir temp_dir_;
- ScopedTempDir temp_dir_2_;
-
- // The link file to be created/updated in the shortcut tests below.
- FilePath link_file_;
-
- // Properties for the created shortcut.
- ShortcutProperties link_properties_;
-
- // Properties for the updated shortcut.
- ShortcutProperties link_properties_2_;
-};
-
-} // namespace
-
-TEST_F(ShortcutTest, CreateAndResolveShortcutProperties) {
- // Test all properties.
- FilePath file_1(temp_dir_.GetPath().Append(L"Link1.lnk"));
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- file_1, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties properties_read_1;
- ASSERT_TRUE(ResolveShortcutProperties(
- file_1, ShortcutProperties::PROPERTIES_ALL, &properties_read_1));
- EXPECT_EQ(static_cast<unsigned>(ShortcutProperties::PROPERTIES_ALL),
- properties_read_1.options);
- ValidatePathsAreEqual(link_properties_.target, properties_read_1.target);
- ValidatePathsAreEqual(link_properties_.working_dir,
- properties_read_1.working_dir);
- EXPECT_EQ(link_properties_.arguments, properties_read_1.arguments);
- EXPECT_EQ(link_properties_.description, properties_read_1.description);
- ValidatePathsAreEqual(link_properties_.icon, properties_read_1.icon);
- EXPECT_EQ(link_properties_.icon_index, properties_read_1.icon_index);
- EXPECT_EQ(link_properties_.app_id, properties_read_1.app_id);
- EXPECT_EQ(link_properties_.dual_mode, properties_read_1.dual_mode);
- EXPECT_EQ(link_properties_.toast_activator_clsid,
- properties_read_1.toast_activator_clsid);
-
- // Test simple shortcut with no special properties set.
- FilePath file_2(temp_dir_.GetPath().Append(L"Link2.lnk"));
- ShortcutProperties only_target_properties;
- only_target_properties.set_target(link_properties_.target);
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- file_2, only_target_properties, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties properties_read_2;
- ASSERT_TRUE(ResolveShortcutProperties(
- file_2, ShortcutProperties::PROPERTIES_ALL, &properties_read_2));
- EXPECT_EQ(static_cast<unsigned>(ShortcutProperties::PROPERTIES_ALL),
- properties_read_2.options);
- ValidatePathsAreEqual(only_target_properties.target,
- properties_read_2.target);
- ValidatePathsAreEqual(FilePath(), properties_read_2.working_dir);
- EXPECT_EQ(L"", properties_read_2.arguments);
- EXPECT_EQ(L"", properties_read_2.description);
- ValidatePathsAreEqual(FilePath(), properties_read_2.icon);
- EXPECT_EQ(0, properties_read_2.icon_index);
- EXPECT_EQ(L"", properties_read_2.app_id);
- EXPECT_FALSE(properties_read_2.dual_mode);
- EXPECT_EQ(CLSID_NULL, properties_read_2.toast_activator_clsid);
-}
-
-TEST_F(ShortcutTest, CreateAndResolveShortcut) {
- ShortcutProperties only_target_properties;
- only_target_properties.set_target(link_properties_.target);
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, only_target_properties, SHORTCUT_CREATE_ALWAYS));
-
- FilePath resolved_name;
- EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, NULL));
-
- char read_contents[arraysize(kFileContents)];
- base::ReadFile(resolved_name, read_contents, arraysize(read_contents));
- EXPECT_STREQ(kFileContents, read_contents);
-}
-
-TEST_F(ShortcutTest, ResolveShortcutWithArgs) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- FilePath resolved_name;
- string16 args;
- EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, &args));
-
- char read_contents[arraysize(kFileContents)];
- base::ReadFile(resolved_name, read_contents, arraysize(read_contents));
- EXPECT_STREQ(kFileContents, read_contents);
- EXPECT_EQ(link_properties_.arguments, args);
-}
-
-TEST_F(ShortcutTest, CreateShortcutWithOnlySomeProperties) {
- ShortcutProperties target_and_args_properties;
- target_and_args_properties.set_target(link_properties_.target);
- target_and_args_properties.set_arguments(link_properties_.arguments);
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, target_and_args_properties,
- SHORTCUT_CREATE_ALWAYS));
-
- ValidateShortcut(link_file_, target_and_args_properties);
-}
-
-TEST_F(ShortcutTest, CreateShortcutVerifyProperties) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ValidateShortcut(link_file_, link_properties_);
-}
-
-TEST_F(ShortcutTest, UpdateShortcutVerifyProperties) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_2_, SHORTCUT_UPDATE_EXISTING));
-
- ValidateShortcut(link_file_, link_properties_2_);
-}
-
-TEST_F(ShortcutTest, UpdateShortcutUpdateOnlyTargetAndResolve) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties update_only_target_properties;
- update_only_target_properties.set_target(link_properties_2_.target);
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, update_only_target_properties,
- SHORTCUT_UPDATE_EXISTING));
-
- ShortcutProperties expected_properties = link_properties_;
- expected_properties.set_target(link_properties_2_.target);
- ValidateShortcut(link_file_, expected_properties);
-
- FilePath resolved_name;
- EXPECT_TRUE(ResolveShortcut(link_file_, &resolved_name, NULL));
-
- char read_contents[arraysize(kFileContents2)];
- base::ReadFile(resolved_name, read_contents, arraysize(read_contents));
- EXPECT_STREQ(kFileContents2, read_contents);
-}
-
-TEST_F(ShortcutTest, UpdateShortcutMakeDualMode) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties make_dual_mode_properties;
- make_dual_mode_properties.set_dual_mode(true);
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, make_dual_mode_properties,
- SHORTCUT_UPDATE_EXISTING));
-
- ShortcutProperties expected_properties = link_properties_;
- expected_properties.set_dual_mode(true);
- ValidateShortcut(link_file_, expected_properties);
-}
-
-TEST_F(ShortcutTest, UpdateShortcutRemoveDualMode) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_2_, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties remove_dual_mode_properties;
- remove_dual_mode_properties.set_dual_mode(false);
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, remove_dual_mode_properties,
- SHORTCUT_UPDATE_EXISTING));
-
- ShortcutProperties expected_properties = link_properties_2_;
- expected_properties.set_dual_mode(false);
- ValidateShortcut(link_file_, expected_properties);
-}
-
-TEST_F(ShortcutTest, UpdateShortcutClearArguments) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties clear_arguments_properties;
- clear_arguments_properties.set_arguments(string16());
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, clear_arguments_properties,
- SHORTCUT_UPDATE_EXISTING));
-
- ShortcutProperties expected_properties = link_properties_;
- expected_properties.set_arguments(string16());
- ValidateShortcut(link_file_, expected_properties);
-}
-
-TEST_F(ShortcutTest, FailUpdateShortcutThatDoesNotExist) {
- ASSERT_FALSE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_UPDATE_EXISTING));
- ASSERT_FALSE(PathExists(link_file_));
-}
-
-TEST_F(ShortcutTest, ReplaceShortcutAllProperties) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_2_, SHORTCUT_REPLACE_EXISTING));
-
- ValidateShortcut(link_file_, link_properties_2_);
-}
-
-TEST_F(ShortcutTest, ReplaceShortcutSomeProperties) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- ShortcutProperties new_properties;
- new_properties.set_target(link_properties_2_.target);
- new_properties.set_arguments(link_properties_2_.arguments);
- new_properties.set_description(link_properties_2_.description);
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, new_properties, SHORTCUT_REPLACE_EXISTING));
-
- // Expect only properties in |new_properties| to be set, all other properties
- // should have been overwritten.
- ShortcutProperties expected_properties(new_properties);
- expected_properties.set_working_dir(FilePath());
- expected_properties.set_icon(FilePath(), 0);
- expected_properties.set_app_id(string16());
- expected_properties.set_dual_mode(false);
- ValidateShortcut(link_file_, expected_properties);
-}
-
-TEST_F(ShortcutTest, FailReplaceShortcutThatDoesNotExist) {
- ASSERT_FALSE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_REPLACE_EXISTING));
- ASSERT_FALSE(PathExists(link_file_));
-}
-
-// Test that the old arguments remain on the replaced shortcut when not
-// otherwise specified.
-TEST_F(ShortcutTest, ReplaceShortcutKeepOldArguments) {
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_, SHORTCUT_CREATE_ALWAYS));
-
- // Do not explicitly set the arguments.
- link_properties_2_.options &=
- ~ShortcutProperties::PROPERTIES_ARGUMENTS;
- ASSERT_TRUE(CreateOrUpdateShortcutLink(
- link_file_, link_properties_2_, SHORTCUT_REPLACE_EXISTING));
-
- ShortcutProperties expected_properties(link_properties_2_);
- expected_properties.set_arguments(link_properties_.arguments);
- ValidateShortcut(link_file_, expected_properties);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/startup_information_unittest.cc b/base/win/startup_information_unittest.cc
deleted file mode 100644
index f5d1f37..0000000
--- a/base/win/startup_information_unittest.cc
+++ /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.
-
-#include <windows.h>
-#include <stddef.h>
-
-#include <string>
-
-#include "base/command_line.h"
-#include "base/test/multiprocess_test.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/scoped_process_information.h"
-#include "base/win/startup_information.h"
-#include "testing/multiprocess_func_list.h"
-
-const wchar_t kSectionName[] = L"EventTestSection";
-const size_t kSectionSize = 4096;
-
-MULTIPROCESS_TEST_MAIN(FireInheritedEvents) {
- HANDLE section = ::OpenFileMappingW(PAGE_READWRITE, false, kSectionName);
- HANDLE* events = reinterpret_cast<HANDLE*>(::MapViewOfFile(section,
- PAGE_READWRITE, 0, 0, kSectionSize));
- // This event should not be valid because it wasn't explicitly inherited.
- if (::SetEvent(events[1]))
- return -1;
- // This event should be valid because it was explicitly inherited.
- if (!::SetEvent(events[0]))
- return -1;
-
- return 0;
-}
-
-class StartupInformationTest : public base::MultiProcessTest {};
-
-// Verify that only the explicitly specified event is inherited.
-TEST_F(StartupInformationTest, InheritStdOut) {
- base::win::StartupInformation startup_info;
-
- HANDLE section = ::CreateFileMappingW(INVALID_HANDLE_VALUE, NULL,
- PAGE_READWRITE, 0, kSectionSize,
- kSectionName);
- ASSERT_TRUE(section);
-
- HANDLE* events = reinterpret_cast<HANDLE*>(::MapViewOfFile(section,
- FILE_MAP_READ | FILE_MAP_WRITE, 0, 0, kSectionSize));
-
- // Make two inheritable events.
- SECURITY_ATTRIBUTES security_attributes = { sizeof(security_attributes),
- NULL, true };
- events[0] = ::CreateEvent(&security_attributes, false, false, NULL);
- ASSERT_TRUE(events[0]);
- events[1] = ::CreateEvent(&security_attributes, false, false, NULL);
- ASSERT_TRUE(events[1]);
-
- ASSERT_TRUE(startup_info.InitializeProcThreadAttributeList(1));
- ASSERT_TRUE(startup_info.UpdateProcThreadAttribute(
- PROC_THREAD_ATTRIBUTE_HANDLE_LIST, &events[0],
- sizeof(events[0])));
-
- std::wstring cmd_line =
- MakeCmdLine("FireInheritedEvents").GetCommandLineString();
-
- PROCESS_INFORMATION temp_process_info = {};
- ASSERT_TRUE(::CreateProcess(NULL, &cmd_line[0],
- NULL, NULL, true, EXTENDED_STARTUPINFO_PRESENT,
- NULL, NULL, startup_info.startup_info(),
- &temp_process_info)) << ::GetLastError();
- base::win::ScopedProcessInformation process_info(temp_process_info);
-
- // Only the first event should be signalled
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForMultipleObjects(2, events, false,
- 4000));
-}
-
diff --git a/base/win/typed_event_handler_unittest.cc b/base/win/typed_event_handler_unittest.cc
deleted file mode 100644
index 76dba80..0000000
--- a/base/win/typed_event_handler_unittest.cc
+++ /dev/null
@@ -1,49 +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/win/typed_event_handler.h"
-
-#include <windows.foundation.h>
-
-#include "base/test/bind_test_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-TEST(TypedEventHandlerTest, InvokeSuccess) {
- bool called_callback = false;
- TypedEventHandler<IInspectable*, IInspectable*> handler(
- base::BindLambdaForTesting([&](IInspectable* sender, IInspectable* args) {
- EXPECT_EQ(reinterpret_cast<IInspectable*>(0x01), sender);
- EXPECT_EQ(reinterpret_cast<IInspectable*>(0x02), args);
- called_callback = true;
- return S_OK;
- }));
-
- EXPECT_FALSE(called_callback);
- HRESULT hr = handler.Invoke(reinterpret_cast<IInspectable*>(0x01),
- reinterpret_cast<IInspectable*>(0x02));
- EXPECT_TRUE(called_callback);
- EXPECT_EQ(S_OK, hr);
-}
-
-TEST(TypedEventHandlerTest, InvokeFail) {
- bool called_callback = false;
- TypedEventHandler<IInspectable*, IInspectable*> handler(
- base::BindLambdaForTesting([&](IInspectable* sender, IInspectable* args) {
- EXPECT_EQ(nullptr, sender);
- EXPECT_EQ(nullptr, args);
- called_callback = true;
- return E_FAIL;
- }));
-
- EXPECT_FALSE(called_callback);
- HRESULT hr = handler.Invoke(nullptr, nullptr);
- EXPECT_TRUE(called_callback);
- EXPECT_EQ(E_FAIL, hr);
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/wait_chain_unittest.cc b/base/win/wait_chain_unittest.cc
deleted file mode 100644
index 74a0ce5..0000000
--- a/base/win/wait_chain_unittest.cc
+++ /dev/null
@@ -1,317 +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/win/wait_chain.h"
-
-#include <memory>
-#include <string>
-
-#include "base/bind.h"
-#include "base/callback.h"
-#include "base/command_line.h"
-#include "base/strings/string_number_conversions.h"
-#include "base/strings/string_piece.h"
-#include "base/test/multiprocess_test.h"
-#include "base/threading/simple_thread.h"
-#include "base/win/win_util.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/multiprocess_func_list.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-// Appends |handle| as a command line switch.
-void AppendSwitchHandle(CommandLine* command_line,
- StringPiece switch_name,
- HANDLE handle) {
- command_line->AppendSwitchASCII(switch_name.as_string(),
- UintToString(HandleToUint32(handle)));
-}
-
-// Retrieves the |handle| associated to |switch_name| from the command line.
-ScopedHandle GetSwitchValueHandle(CommandLine* command_line,
- StringPiece switch_name) {
- std::string switch_string =
- command_line->GetSwitchValueASCII(switch_name.as_string());
- unsigned int switch_uint = 0;
- if (switch_string.empty() || !StringToUint(switch_string, &switch_uint)) {
- DLOG(ERROR) << "Missing or invalid " << switch_name << " argument.";
- return ScopedHandle();
- }
- return ScopedHandle(reinterpret_cast<HANDLE>(switch_uint));
-}
-
-// Helper function to create a mutex.
-ScopedHandle CreateMutex(bool inheritable) {
- SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
- nullptr, inheritable};
- return ScopedHandle(::CreateMutex(&security_attributes, FALSE, NULL));
-}
-
-// Helper function to create an event.
-ScopedHandle CreateEvent(bool inheritable) {
- SECURITY_ATTRIBUTES security_attributes = {sizeof(SECURITY_ATTRIBUTES),
- nullptr, inheritable};
- return ScopedHandle(
- ::CreateEvent(&security_attributes, FALSE, FALSE, nullptr));
-}
-
-// Helper thread class that runs the callback then stops.
-class SingleTaskThread : public SimpleThread {
- public:
- explicit SingleTaskThread(const Closure& task)
- : SimpleThread("WaitChainTest SingleTaskThread"), task_(task) {}
-
- void Run() override { task_.Run(); }
-
- private:
- Closure task_;
-
- DISALLOW_COPY_AND_ASSIGN(SingleTaskThread);
-};
-
-// Helper thread to cause a deadlock by acquiring 2 mutexes in a given order.
-class DeadlockThread : public SimpleThread {
- public:
- DeadlockThread(HANDLE mutex_1, HANDLE mutex_2)
- : SimpleThread("WaitChainTest DeadlockThread"),
- wait_event_(CreateEvent(false)),
- mutex_acquired_event_(CreateEvent(false)),
- mutex_1_(mutex_1),
- mutex_2_(mutex_2) {}
-
- void Run() override {
- // Acquire the mutex then signal the main thread.
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(mutex_1_, INFINITE));
- EXPECT_TRUE(::SetEvent(mutex_acquired_event_.Get()));
-
- // Wait until both threads are holding their mutex before trying to acquire
- // the other one.
- EXPECT_EQ(WAIT_OBJECT_0,
- ::WaitForSingleObject(wait_event_.Get(), INFINITE));
-
- // To unblock the deadlock, one of the threads will get terminated (via
- // TerminateThread()) without releasing the mutex. This causes the other
- // thread to wake up with WAIT_ABANDONED.
- EXPECT_EQ(WAIT_ABANDONED, ::WaitForSingleObject(mutex_2_, INFINITE));
- }
-
- // Blocks until a mutex is acquired.
- void WaitForMutexAcquired() {
- EXPECT_EQ(WAIT_OBJECT_0,
- ::WaitForSingleObject(mutex_acquired_event_.Get(), INFINITE));
- }
-
- // Signal the thread to acquire the second mutex.
- void SignalToAcquireMutex() { EXPECT_TRUE(::SetEvent(wait_event_.Get())); }
-
- // Terminates the thread.
- bool Terminate() {
- ScopedHandle thread_handle(::OpenThread(THREAD_TERMINATE, FALSE, tid()));
- return ::TerminateThread(thread_handle.Get(), 0);
- }
-
- private:
- ScopedHandle wait_event_;
- ScopedHandle mutex_acquired_event_;
-
- // The 2 mutex to acquire.
- HANDLE mutex_1_;
- HANDLE mutex_2_;
-
- DISALLOW_COPY_AND_ASSIGN(DeadlockThread);
-};
-
-// Creates a thread that joins |thread_to_join| and then terminates when it
-// finishes execution.
-std::unique_ptr<SingleTaskThread> CreateJoiningThread(
- SimpleThread* thread_to_join) {
- std::unique_ptr<SingleTaskThread> thread(new SingleTaskThread(
- Bind(&SimpleThread::Join, Unretained(thread_to_join))));
- thread->Start();
-
- return thread;
-}
-
-// Creates a thread that calls WaitForSingleObject() on the handle and then
-// terminates when it unblocks.
-std::unique_ptr<SingleTaskThread> CreateWaitingThread(HANDLE handle) {
- std::unique_ptr<SingleTaskThread> thread(new SingleTaskThread(
- Bind(IgnoreResult(&::WaitForSingleObject), handle, INFINITE)));
- thread->Start();
-
- return thread;
-}
-
-// Creates a thread that blocks on |mutex_2| after acquiring |mutex_1|.
-std::unique_ptr<DeadlockThread> CreateDeadlockThread(HANDLE mutex_1,
- HANDLE mutex_2) {
- std::unique_ptr<DeadlockThread> thread(new DeadlockThread(mutex_1, mutex_2));
- thread->Start();
-
- // Wait until the first mutex is acquired before returning.
- thread->WaitForMutexAcquired();
-
- return thread;
-}
-
-// Child process to test the cross-process capability of the WCT api.
-// This process will simulate a hang while holding a mutex that the parent
-// process is waiting on.
-MULTIPROCESS_TEST_MAIN(WaitChainTestProc) {
- CommandLine* command_line = CommandLine::ForCurrentProcess();
-
- ScopedHandle mutex = GetSwitchValueHandle(command_line, "mutex");
- CHECK(mutex.IsValid());
-
- ScopedHandle sync_event(GetSwitchValueHandle(command_line, "sync_event"));
- CHECK(sync_event.IsValid());
-
- // Acquire mutex.
- CHECK(::WaitForSingleObject(mutex.Get(), INFINITE) == WAIT_OBJECT_0);
-
- // Signal back to the parent process that the mutex is hold.
- CHECK(::SetEvent(sync_event.Get()));
-
- // Wait on a signal from the parent process before terminating.
- CHECK(::WaitForSingleObject(sync_event.Get(), INFINITE) == WAIT_OBJECT_0);
-
- return 0;
-}
-
-// Start a child process and passes the |mutex| and the |sync_event| to the
-// command line.
-Process StartChildProcess(HANDLE mutex, HANDLE sync_event) {
- CommandLine command_line = GetMultiProcessTestChildBaseCommandLine();
-
- AppendSwitchHandle(&command_line, "mutex", mutex);
- AppendSwitchHandle(&command_line, "sync_event", sync_event);
-
- LaunchOptions options;
- options.handles_to_inherit.push_back(mutex);
- options.handles_to_inherit.push_back(sync_event);
- return SpawnMultiProcessTestChild("WaitChainTestProc", command_line, options);
-}
-
-// Returns true if the |wait_chain| is an alternating sequence of thread objects
-// and synchronization objects.
-bool WaitChainStructureIsCorrect(const WaitChainNodeVector& wait_chain) {
- // Checks thread objects.
- for (size_t i = 0; i < wait_chain.size(); i += 2) {
- if (wait_chain[i].ObjectType != WctThreadType)
- return false;
- }
-
- // Check synchronization objects.
- for (size_t i = 1; i < wait_chain.size(); i += 2) {
- if (wait_chain[i].ObjectType == WctThreadType)
- return false;
- }
- return true;
-}
-
-// Returns true if the |wait_chain| goes through more than 1 process.
-bool WaitChainIsCrossProcess(const WaitChainNodeVector& wait_chain) {
- if (wait_chain.size() == 0)
- return false;
-
- // Just check that the process id changes somewhere in the chain.
- // Note: ThreadObjects are every 2 nodes.
- DWORD first_process = wait_chain[0].ThreadObject.ProcessId;
- for (size_t i = 2; i < wait_chain.size(); i += 2) {
- if (first_process != wait_chain[i].ThreadObject.ProcessId)
- return true;
- }
- return false;
-}
-
-} // namespace
-
-// Creates 2 threads that acquire their designated mutex and then try to
-// acquire each others' mutex to cause a deadlock.
-TEST(WaitChainTest, Deadlock) {
- // 2 mutexes are needed to get a deadlock.
- ScopedHandle mutex_1 = CreateMutex(false);
- ASSERT_TRUE(mutex_1.IsValid());
- ScopedHandle mutex_2 = CreateMutex(false);
- ASSERT_TRUE(mutex_2.IsValid());
-
- std::unique_ptr<DeadlockThread> deadlock_thread_1 =
- CreateDeadlockThread(mutex_1.Get(), mutex_2.Get());
- std::unique_ptr<DeadlockThread> deadlock_thread_2 =
- CreateDeadlockThread(mutex_2.Get(), mutex_1.Get());
-
- // Signal the threads to try to acquire the other mutex.
- deadlock_thread_1->SignalToAcquireMutex();
- deadlock_thread_2->SignalToAcquireMutex();
- // Sleep to make sure the 2 threads got a chance to execute.
- Sleep(10);
-
- // Create a few waiting threads to get a longer wait chain.
- std::unique_ptr<SingleTaskThread> waiting_thread_1 =
- CreateJoiningThread(deadlock_thread_1.get());
- std::unique_ptr<SingleTaskThread> waiting_thread_2 =
- CreateJoiningThread(waiting_thread_1.get());
-
- WaitChainNodeVector wait_chain;
- bool is_deadlock;
- ASSERT_TRUE(GetThreadWaitChain(waiting_thread_2->tid(), &wait_chain,
- &is_deadlock, nullptr, nullptr));
-
- EXPECT_EQ(9U, wait_chain.size());
- EXPECT_TRUE(is_deadlock);
- EXPECT_TRUE(WaitChainStructureIsCorrect(wait_chain));
- EXPECT_FALSE(WaitChainIsCrossProcess(wait_chain));
-
- ASSERT_TRUE(deadlock_thread_1->Terminate());
-
- // The SimpleThread API expect Join() to be called before destruction.
- deadlock_thread_2->Join();
- waiting_thread_2->Join();
-}
-
-// Creates a child process that acquires a mutex and then blocks. A chain of
-// threads then blocks on that mutex.
-TEST(WaitChainTest, CrossProcess) {
- ScopedHandle mutex = CreateMutex(true);
- ASSERT_TRUE(mutex.IsValid());
- ScopedHandle sync_event = CreateEvent(true);
- ASSERT_TRUE(sync_event.IsValid());
-
- Process child_process = StartChildProcess(mutex.Get(), sync_event.Get());
- ASSERT_TRUE(child_process.IsValid());
-
- // Wait for the child process to signal when it's holding the mutex.
- EXPECT_EQ(WAIT_OBJECT_0, ::WaitForSingleObject(sync_event.Get(), INFINITE));
-
- // Create a few waiting threads to get a longer wait chain.
- std::unique_ptr<SingleTaskThread> waiting_thread_1 =
- CreateWaitingThread(mutex.Get());
- std::unique_ptr<SingleTaskThread> waiting_thread_2 =
- CreateJoiningThread(waiting_thread_1.get());
- std::unique_ptr<SingleTaskThread> waiting_thread_3 =
- CreateJoiningThread(waiting_thread_2.get());
-
- WaitChainNodeVector wait_chain;
- bool is_deadlock;
- ASSERT_TRUE(GetThreadWaitChain(waiting_thread_3->tid(), &wait_chain,
- &is_deadlock, nullptr, nullptr));
-
- EXPECT_EQ(7U, wait_chain.size());
- EXPECT_FALSE(is_deadlock);
- EXPECT_TRUE(WaitChainStructureIsCorrect(wait_chain));
- EXPECT_TRUE(WaitChainIsCrossProcess(wait_chain));
-
- // Unblock child process and wait for it to terminate.
- ASSERT_TRUE(::SetEvent(sync_event.Get()));
- ASSERT_TRUE(child_process.WaitForExit(nullptr));
-
- // The SimpleThread API expect Join() to be called before destruction.
- waiting_thread_3->Join();
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/win_includes_unittest.cc b/base/win/win_includes_unittest.cc
deleted file mode 100644
index 20c6cbc..0000000
--- a/base/win/win_includes_unittest.cc
+++ /dev/null
@@ -1,33 +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.
-
-// This file ensures that these header files don't include Windows.h and can
-// compile without including Windows.h. This helps to improve compile times.
-
-#include "base/atomicops.h"
-#include "base/files/file_util.h"
-#include "base/files/platform_file.h"
-#include "base/process/process_handle.h"
-#include "base/synchronization/condition_variable.h"
-#include "base/synchronization/lock.h"
-#include "base/threading/platform_thread.h"
-#include "base/threading/thread_local_storage.h"
-#include "base/win/registry.h"
-#include "base/win/scoped_handle.h"
-#include "base/win/win_util.h"
-
-#ifdef _WINDOWS_
-#error Windows.h was included inappropriately.
-#endif
-
-// Make sure windows.h can be included after windows_types.h
-#include "base/win/windows_types.h"
-
-#include <windows.h>
-
-// Check that type sizes match.
-static_assert(sizeof(CHROME_CONDITION_VARIABLE) == sizeof(CONDITION_VARIABLE),
- "Definition mismatch.");
-static_assert(sizeof(CHROME_SRWLOCK) == sizeof(SRWLOCK),
- "Definition mismatch.");
diff --git a/base/win/win_util_unittest.cc b/base/win/win_util_unittest.cc
deleted file mode 100644
index 6d5cf61..0000000
--- a/base/win/win_util_unittest.cc
+++ /dev/null
@@ -1,82 +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/win/win_util.h"
-
-#include "base/files/file_path.h"
-#include "base/macros.h"
-#include "base/scoped_native_library.h"
-#include "base/stl_util.h"
-#include "base/win/win_client_metrics.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-namespace {
-
-// Saves the current thread's locale ID when initialized, and restores it when
-// the instance is going out of scope.
-class ThreadLocaleSaver {
- public:
- ThreadLocaleSaver() : original_locale_id_(GetThreadLocale()) {}
- ~ThreadLocaleSaver() { SetThreadLocale(original_locale_id_); }
-
- private:
- LCID original_locale_id_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreadLocaleSaver);
-};
-
-} // namespace
-
-// The test is somewhat silly, because some bots some have UAC enabled and some
-// have it disabled. At least we check that it does not crash.
-TEST(BaseWinUtilTest, TestIsUACEnabled) {
- UserAccountControlIsEnabled();
-}
-
-TEST(BaseWinUtilTest, TestGetUserSidString) {
- std::wstring user_sid;
- EXPECT_TRUE(GetUserSidString(&user_sid));
- EXPECT_TRUE(!user_sid.empty());
-}
-
-TEST(BaseWinUtilTest, TestGetNonClientMetrics) {
- NONCLIENTMETRICS_XP metrics = {0};
- GetNonClientMetrics(&metrics);
- EXPECT_GT(metrics.cbSize, 0u);
- EXPECT_GT(metrics.iScrollWidth, 0);
- EXPECT_GT(metrics.iScrollHeight, 0);
-}
-
-TEST(BaseWinUtilTest, TestGetLoadedModulesSnapshot) {
- std::vector<HMODULE> snapshot;
-
- ASSERT_TRUE(GetLoadedModulesSnapshot(::GetCurrentProcess(), &snapshot));
- size_t original_snapshot_size = snapshot.size();
- ASSERT_GT(original_snapshot_size, 0u);
- snapshot.clear();
-
- // Load in a new module. Pick msvidc32.dll as it is present from WinXP to
- // Win10 and yet rarely used.
- const wchar_t dll_name[] = L"msvidc32.dll";
- ASSERT_EQ(NULL, ::GetModuleHandle(dll_name));
-
- base::ScopedNativeLibrary new_dll((base::FilePath(dll_name)));
- ASSERT_NE(static_cast<HMODULE>(NULL), new_dll.get());
- ASSERT_TRUE(GetLoadedModulesSnapshot(::GetCurrentProcess(), &snapshot));
- ASSERT_GT(snapshot.size(), original_snapshot_size);
- ASSERT_TRUE(base::ContainsValue(snapshot, new_dll.get()));
-}
-
-TEST(BaseWinUtilTest, TestUint32ToInvalidHandle) {
- // Ensure that INVALID_HANDLE_VALUE is preserved when going to a 32-bit value
- // and back on 64-bit platforms.
- uint32_t invalid_handle = base::win::HandleToUint32(INVALID_HANDLE_VALUE);
- EXPECT_EQ(INVALID_HANDLE_VALUE, base::win::Uint32ToHandle(invalid_handle));
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/windows_version_unittest.cc b/base/win/windows_version_unittest.cc
deleted file mode 100644
index f0d6d96..0000000
--- a/base/win/windows_version_unittest.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/win/windows_version.h"
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-namespace {
-
-TEST(WindowsVersion, GetVersionExAndKernelVersionMatch) {
- // If this fails, we're running in compatibility mode, or need to update the
- // application manifest.
- EXPECT_EQ(OSInfo::GetInstance()->version(),
- OSInfo::GetInstance()->Kernel32Version());
-}
-
-} // namespace
-} // namespace win
-} // namespace base
diff --git a/base/win/winrt_storage_util_unittest.cc b/base/win/winrt_storage_util_unittest.cc
deleted file mode 100644
index 530ab23..0000000
--- a/base/win/winrt_storage_util_unittest.cc
+++ /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.
-
-#include "base/win/winrt_storage_util.h"
-
-#include <string.h>
-#include <wrl/client.h>
-
-#include "base/strings/string_util.h"
-#include "base/win/core_winrt_util.h"
-#include "base/win/scoped_com_initializer.h"
-#include "base/win/scoped_hstring.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace base {
-namespace win {
-
-TEST(WinrtStorageUtilTest, CreateBufferFromData) {
- ScopedCOMInitializer com_initializer(ScopedCOMInitializer::kMTA);
-
- if (!ResolveCoreWinRTDelayload() ||
- !ScopedHString::ResolveCoreWinRTStringDelayload()) {
- return;
- }
-
- const std::vector<uint8_t> data = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
- Microsoft::WRL::ComPtr<ABI::Windows::Storage::Streams::IBuffer> buffer;
- ASSERT_HRESULT_SUCCEEDED(
- CreateIBufferFromData(data.data(), data.size(), &buffer));
-
- uint8_t* p_buffer_data;
- uint32_t length;
- ASSERT_HRESULT_SUCCEEDED(
- GetPointerToBufferData(buffer.Get(), &p_buffer_data, &length));
-
- ASSERT_EQ(data.size(), length);
- EXPECT_EQ(0, memcmp(p_buffer_data, data.data(), data.size()));
-}
-
-} // namespace win
-} // namespace base
diff --git a/base/win/wrapped_window_proc_unittest.cc b/base/win/wrapped_window_proc_unittest.cc
deleted file mode 100644
index 25ba2d4..0000000
--- a/base/win/wrapped_window_proc_unittest.cc
+++ /dev/null
@@ -1,78 +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/win/wrapped_window_proc.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace {
-
-DWORD kExceptionCode = 12345;
-WPARAM kCrashMsg = 98765;
-
-// A trivial WindowProc that generates an exception.
-LRESULT CALLBACK TestWindowProc(HWND hwnd, UINT message,
- WPARAM wparam, LPARAM lparam) {
- if (message == kCrashMsg)
- RaiseException(kExceptionCode, 0, 0, NULL);
- return DefWindowProc(hwnd, message, wparam, lparam);
-}
-
-// This class implements an exception filter that can be queried about a past
-// exception.
-class TestWrappedExceptionFiter {
- public:
- TestWrappedExceptionFiter() : called_(false) {
- EXPECT_FALSE(s_filter_);
- s_filter_ = this;
- }
-
- ~TestWrappedExceptionFiter() {
- EXPECT_EQ(s_filter_, this);
- s_filter_ = NULL;
- }
-
- bool called() {
- return called_;
- }
-
- // The actual exception filter just records the exception.
- static int Filter(EXCEPTION_POINTERS* info) {
- EXPECT_FALSE(s_filter_->called_);
- if (info->ExceptionRecord->ExceptionCode == kExceptionCode)
- s_filter_->called_ = true;
- return EXCEPTION_EXECUTE_HANDLER;
- }
-
- private:
- bool called_;
- static TestWrappedExceptionFiter* s_filter_;
-};
-TestWrappedExceptionFiter* TestWrappedExceptionFiter::s_filter_ = NULL;
-
-} // namespace.
-
-TEST(WrappedWindowProc, CatchesExceptions) {
- HINSTANCE hinst = GetModuleHandle(NULL);
- std::wstring class_name(L"TestClass");
-
- WNDCLASS wc = {0};
- wc.lpfnWndProc = base::win::WrappedWindowProc<TestWindowProc>;
- wc.hInstance = hinst;
- wc.lpszClassName = class_name.c_str();
- RegisterClass(&wc);
-
- HWND window = CreateWindow(class_name.c_str(), 0, 0, 0, 0, 0, 0, HWND_MESSAGE,
- 0, hinst, 0);
- ASSERT_TRUE(window);
-
- // Before generating the exception we make sure that the filter will see it.
- TestWrappedExceptionFiter wrapper;
- base::win::WinProcExceptionFilter old_filter =
- base::win::SetWinProcExceptionFilter(TestWrappedExceptionFiter::Filter);
-
- SendMessage(window, kCrashMsg, 0, 0);
- EXPECT_TRUE(wrapper.called());
-
- base::win::SetWinProcExceptionFilter(old_filter);
-}