Commit 44ac0470 authored by Sergio Villar Senin's avatar Sergio Villar Senin Committed by Commit Bot

OnionSoup: move MemoryInfoTest to TestMockTimeTaskRunner

This is a followup of http://crrev.com/c/1588650. In this CL MemoryInfoTest is
moved out of time function overrides. TestMockTimeTaskRunner is used instead.

Overriding the time functions is no longer required as the mock clock provided
by the test task runner has all the required features, basically moving time
forward at will.

Bug: 919383
Change-Id: I13ac8b2436d0b07da1374dee189372619ecbfbda
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1590103
Commit-Queue: Sergio Villar <svillar@igalia.com>
Reviewed-by: default avatarNicolás Peña Moreno <npm@chromium.org>
Cr-Commit-Position: refs/heads/master@{#664711}
parent d554c5fc
...@@ -33,12 +33,12 @@ ...@@ -33,12 +33,12 @@
#include <limits> #include <limits>
#include "base/macros.h" #include "base/macros.h"
#include "base/time/default_tick_clock.h"
#include "third_party/blink/renderer/core/frame/local_frame.h" #include "third_party/blink/renderer/core/frame/local_frame.h"
#include "third_party/blink/renderer/core/frame/settings.h" #include "third_party/blink/renderer/core/frame/settings.h"
#include "third_party/blink/renderer/platform/runtime_enabled_features.h" #include "third_party/blink/renderer/platform/runtime_enabled_features.h"
#include "third_party/blink/renderer/platform/wtf/math_extras.h" #include "third_party/blink/renderer/platform/wtf/math_extras.h"
#include "third_party/blink/renderer/platform/wtf/thread_specific.h" #include "third_party/blink/renderer/platform/wtf/thread_specific.h"
#include "third_party/blink/renderer/platform/wtf/time.h"
#include "v8/include/v8.h" #include "v8/include/v8.h"
namespace blink { namespace blink {
...@@ -64,7 +64,7 @@ class HeapSizeCache { ...@@ -64,7 +64,7 @@ class HeapSizeCache {
USING_FAST_MALLOC(HeapSizeCache); USING_FAST_MALLOC(HeapSizeCache);
public: public:
HeapSizeCache() {} HeapSizeCache() : clock_(base::DefaultTickClock::GetInstance()) {}
void GetCachedHeapSize(HeapInfo& info, MemoryInfo::Precision precision) { void GetCachedHeapSize(HeapInfo& info, MemoryInfo::Precision precision) {
MaybeUpdate(precision); MaybeUpdate(precision);
...@@ -77,13 +77,16 @@ class HeapSizeCache { ...@@ -77,13 +77,16 @@ class HeapSizeCache {
return *heap_size_cache; return *heap_size_cache;
} }
void SetTickClockForTesting(const base::TickClock* clock) { clock_ = clock; }
void ResetLastUpdateTimeForTesting() { last_update_time_ = base::nullopt; }
private: private:
void MaybeUpdate(MemoryInfo::Precision precision) { void MaybeUpdate(MemoryInfo::Precision precision) {
// We rate-limit queries to once every twenty minutes in the Bucketized case // We rate-limit queries to once every twenty minutes in the Bucketized case
// to make it more difficult for attackers to compare memory usage before // to make it more difficult for attackers to compare memory usage before
// and after some event. We limit to once every 50 ms in the Precise case to // and after some event. We limit to once every 50 ms in the Precise case to
// avoid exposing precise GC timings. // avoid exposing precise GC timings.
TimeTicks now = CurrentTimeTicks(); TimeTicks now = clock_->NowTicks();
TimeDelta delta_allowed = precision == MemoryInfo::Precision::Bucketized TimeDelta delta_allowed = precision == MemoryInfo::Precision::Bucketized
? kTwentyMinutes ? kTwentyMinutes
: kFiftyMs; : kFiftyMs;
...@@ -109,6 +112,7 @@ class HeapSizeCache { ...@@ -109,6 +112,7 @@ class HeapSizeCache {
} }
base::Optional<TimeTicks> last_update_time_; base::Optional<TimeTicks> last_update_time_;
const base::TickClock* clock_;
HeapInfo info_; HeapInfo info_;
DISALLOW_COPY_AND_ASSIGN(HeapSizeCache); DISALLOW_COPY_AND_ASSIGN(HeapSizeCache);
...@@ -180,4 +184,12 @@ MemoryInfo::MemoryInfo(Precision precision) { ...@@ -180,4 +184,12 @@ MemoryInfo::MemoryInfo(Precision precision) {
DCHECK_GT(totalJSHeapSize(), 0u); DCHECK_GT(totalJSHeapSize(), 0u);
} }
// static
void MemoryInfo::SetTickClockForTestingForCurrentThread(
const base::TickClock* clock) {
HeapSizeCache& cache = HeapSizeCache::ForCurrentThread();
cache.SetTickClockForTesting(clock);
cache.ResetLastUpdateTimeForTesting();
}
} // namespace blink } // namespace blink
...@@ -36,6 +36,10 @@ ...@@ -36,6 +36,10 @@
#include "third_party/blink/renderer/platform/heap/handle.h" #include "third_party/blink/renderer/platform/heap/handle.h"
#include "third_party/blink/renderer/platform/wtf/allocator.h" #include "third_party/blink/renderer/platform/wtf/allocator.h"
namespace base {
class TickClock;
}
namespace blink { namespace blink {
struct HeapInfo { struct HeapInfo {
...@@ -72,6 +76,13 @@ class CORE_EXPORT MemoryInfo final : public ScriptWrappable { ...@@ -72,6 +76,13 @@ class CORE_EXPORT MemoryInfo final : public ScriptWrappable {
} }
private: private:
FRIEND_TEST_ALL_PREFIXES(MemoryInfoTest, Bucketized);
FRIEND_TEST_ALL_PREFIXES(MemoryInfoTest, Precise);
friend struct MemoryInfoTestScopedMockTime;
// The caller owns the |clock| which must outlive the MemoryInfo.
static void SetTickClockForTestingForCurrentThread(
const base::TickClock* clock);
HeapInfo info_; HeapInfo info_;
}; };
......
...@@ -30,6 +30,8 @@ ...@@ -30,6 +30,8 @@
#include "third_party/blink/renderer/core/timing/memory_info.h" #include "third_party/blink/renderer/core/timing/memory_info.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/time/default_tick_clock.h"
#include "testing/gtest/include/gtest/gtest.h" #include "testing/gtest/include/gtest/gtest.h"
#include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h" #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_testing.h"
#include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h" #include "third_party/blink/renderer/platform/testing/runtime_enabled_features_test_helpers.h"
...@@ -64,28 +66,8 @@ TEST(MemoryInfo, quantizeMemorySize) { ...@@ -64,28 +66,8 @@ TEST(MemoryInfo, quantizeMemorySize) {
static constexpr int kModForBucketizationCheck = 100000; static constexpr int kModForBucketizationCheck = 100000;
// The current time per the MemoryInfo Tests.
// Use a large value as a start so that when subtracting twenty minutes it does
// not become negative.
static double current_time_ = 60 * 60;
class MemoryInfoTest : public testing::Test { class MemoryInfoTest : public testing::Test {
protected: protected:
void SetUp() override {
// Use a large value so that when subtracting twenty minutes it does not
// become negative. current_time_ = 60 * 60;
original_time_function_ = SetTimeFunctionsForTesting(MockTimeFunction);
// Advance clock by a large amount so that if there were previous MemoryInfo
// values, then they are no longer cached.
AdvanceClock(300 * 60);
}
void TearDown() override {
SetTimeFunctionsForTesting(original_time_function_);
}
void AdvanceClock(double seconds) { current_time_ += seconds; }
void CheckValues(MemoryInfo* info, MemoryInfo::Precision precision) { void CheckValues(MemoryInfo* info, MemoryInfo::Precision precision) {
// Check that used <= total <= limit. // Check that used <= total <= limit.
...@@ -113,11 +95,29 @@ class MemoryInfoTest : public testing::Test { ...@@ -113,11 +95,29 @@ class MemoryInfoTest : public testing::Test {
EXPECT_EQ(info2->usedJSHeapSize(), info->usedJSHeapSize()); EXPECT_EQ(info2->usedJSHeapSize(), info->usedJSHeapSize());
EXPECT_EQ(info2->jsHeapSizeLimit(), info->jsHeapSizeLimit()); EXPECT_EQ(info2->jsHeapSizeLimit(), info->jsHeapSizeLimit());
} }
};
struct MemoryInfoTestScopedMockTime {
MemoryInfoTestScopedMockTime(MemoryInfo::Precision precision) {
MemoryInfo::SetTickClockForTestingForCurrentThread(
test_task_runner_->GetMockTickClock());
}
private: ~MemoryInfoTestScopedMockTime() {
static double MockTimeFunction() { return current_time_; } // MemoryInfo creates a HeapSizeCache object which lives in the current
// thread. This means that it will be shared by all the tests when
// executed sequentially. We must ensure that it ends up in a consistent
// state after each test execution.
MemoryInfo::SetTickClockForTestingForCurrentThread(
base::DefaultTickClock::GetInstance());
}
void AdvanceClock(base::TimeDelta delta) {
test_task_runner_->FastForwardBy(delta);
}
TimeFunction original_time_function_; scoped_refptr<base::TestMockTimeTaskRunner> test_task_runner_ =
base::MakeRefCounted<base::TestMockTimeTaskRunner>();
}; };
TEST_F(MemoryInfoTest, Bucketized) { TEST_F(MemoryInfoTest, Bucketized) {
...@@ -129,6 +129,7 @@ TEST_F(MemoryInfoTest, Bucketized) { ...@@ -129,6 +129,7 @@ TEST_F(MemoryInfoTest, Bucketized) {
// impossible for GC to clear them up unexpectedly early. // impossible for GC to clear them up unexpectedly early.
std::vector<v8::Local<v8::ArrayBuffer>> objects; std::vector<v8::Local<v8::ArrayBuffer>> objects;
MemoryInfoTestScopedMockTime mock_time(MemoryInfo::Precision::Bucketized);
MemoryInfo* bucketized_memory = MemoryInfo* bucketized_memory =
MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized); MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
...@@ -137,7 +138,7 @@ TEST_F(MemoryInfoTest, Bucketized) { ...@@ -137,7 +138,7 @@ TEST_F(MemoryInfoTest, Bucketized) {
// Advance the clock for a minute. Not enough to make bucketized value // Advance the clock for a minute. Not enough to make bucketized value
// recalculate. Also allocate some memory. // recalculate. Also allocate some memory.
AdvanceClock(60); mock_time.AdvanceClock(base::TimeDelta::FromMinutes(1));
objects.push_back(v8::ArrayBuffer::New(isolate, 100)); objects.push_back(v8::ArrayBuffer::New(isolate, 100));
MemoryInfo* bucketized_memory2 = MemoryInfo* bucketized_memory2 =
...@@ -157,7 +158,7 @@ TEST_F(MemoryInfoTest, Bucketized) { ...@@ -157,7 +158,7 @@ TEST_F(MemoryInfoTest, Bucketized) {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
// Advance the clock for another thirty minutes, enough to make the // Advance the clock for another thirty minutes, enough to make the
// bucketized value recalculate. // bucketized value recalculate.
AdvanceClock(60 * 30); mock_time.AdvanceClock(base::TimeDelta::FromMinutes(30));
objects.push_back(v8::ArrayBuffer::New(isolate, 100)); objects.push_back(v8::ArrayBuffer::New(isolate, 100));
MemoryInfo* bucketized_memory3 = MemoryInfo* bucketized_memory3 =
MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized); MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Bucketized);
...@@ -173,6 +174,7 @@ TEST_F(MemoryInfoTest, Precise) { ...@@ -173,6 +174,7 @@ TEST_F(MemoryInfoTest, Precise) {
v8::Isolate* isolate = scope.GetIsolate(); v8::Isolate* isolate = scope.GetIsolate();
std::vector<v8::Local<v8::ArrayBuffer>> objects; std::vector<v8::Local<v8::ArrayBuffer>> objects;
MemoryInfoTestScopedMockTime mock_time(MemoryInfo::Precision::Precise);
MemoryInfo* precise_memory = MemoryInfo* precise_memory =
MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Precise); MakeGarbageCollected<MemoryInfo>(MemoryInfo::Precision::Precise);
// Check that the precise values are monotone and not heavily rounded. // Check that the precise values are monotone and not heavily rounded.
...@@ -180,7 +182,7 @@ TEST_F(MemoryInfoTest, Precise) { ...@@ -180,7 +182,7 @@ TEST_F(MemoryInfoTest, Precise) {
// Advance the clock for a nanosecond, which should not be enough to make the // Advance the clock for a nanosecond, which should not be enough to make the
// precise value recalculate. // precise value recalculate.
AdvanceClock(1e-9); mock_time.AdvanceClock(base::TimeDelta::FromNanoseconds(1));
// Allocate an object in heap and keep it in a vector to make sure that it // Allocate an object in heap and keep it in a vector to make sure that it
// does not get accidentally GC'd. This single ArrayBuffer should be enough to // does not get accidentally GC'd. This single ArrayBuffer should be enough to
// be noticed by the used heap size in the precise MemoryInfo case. // be noticed by the used heap size in the precise MemoryInfo case.
...@@ -193,7 +195,7 @@ TEST_F(MemoryInfoTest, Precise) { ...@@ -193,7 +195,7 @@ TEST_F(MemoryInfoTest, Precise) {
for (int i = 0; i < 10; i++) { for (int i = 0; i < 10; i++) {
// Advance the clock for another thirty seconds, enough to make the precise // Advance the clock for another thirty seconds, enough to make the precise
// values be recalculated. Also allocate another object. // values be recalculated. Also allocate another object.
AdvanceClock(30); mock_time.AdvanceClock(base::TimeDelta::FromSeconds(30));
objects.push_back(v8::ArrayBuffer::New(isolate, 100)); objects.push_back(v8::ArrayBuffer::New(isolate, 100));
MemoryInfo* new_precise_memory = MemoryInfo* new_precise_memory =
...@@ -238,12 +240,11 @@ TEST_F(MemoryInfoTest, FlagEnabled) { ...@@ -238,12 +240,11 @@ TEST_F(MemoryInfoTest, FlagEnabled) {
} }
TEST_F(MemoryInfoTest, ZeroTime) { TEST_F(MemoryInfoTest, ZeroTime) {
// In this test, we make sure that even if the CurrentTimeTicks() value is // In this test, we make sure that even if the current TimeTicks() value is
// very close to 0, we still obtain memory information from the first call to // very close to 0, we still obtain memory information from the first call to
// MakeGarbageCollected<MemoryInfo>. We cannot just subtract // MemoryInfo::Create.
// CurrentTimeTicks() here because many places have DCHECKs for MemoryInfoTestScopedMockTime mock_time(MemoryInfo::Precision::Precise);
// !time.is_null(), which would be hit if we set the clock to be exactly 0. mock_time.AdvanceClock(base::TimeDelta::FromMicroseconds(100));
AdvanceClock(-CurrentTimeTicksInSeconds() + 0.0001);
V8TestingScope scope; V8TestingScope scope;
v8::Isolate* isolate = scope.GetIsolate(); v8::Isolate* isolate = scope.GetIsolate();
std::vector<v8::Local<v8::ArrayBuffer>> objects; std::vector<v8::Local<v8::ArrayBuffer>> objects;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment