internal update

PiperOrigin-RevId: 549351164
This commit is contained in:
Guogang Li
2023-07-19 10:15:19 -07:00
committed by Copybara-Service
parent be5c5b77bd
commit c6566b00c7
7 changed files with 134 additions and 54 deletions
+2
View File
@@ -47,6 +47,7 @@ cc_library(
"//internal/platform/implementation:types",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/container:flat_hash_map",
"@com_google_absl//absl/functional:any_invocable",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
@@ -76,6 +77,7 @@ cc_test(
":test",
"//internal/data:data_manager",
"//internal/network:types",
"//internal/platform:types",
"//internal/platform/implementation:types",
"//internal/platform/implementation/g3", # fixdeps: keep
"@com_github_protobuf_matchers//protobuf-matchers",
+5
View File
@@ -76,4 +76,9 @@ int FakeClock::GetObserversCount() {
return observers_.size();
}
void FakeClock::Reset() {
absl::MutexLock lock(&mutex_);
return observers_.clear();
}
} // namespace nearby
+2
View File
@@ -45,6 +45,8 @@ class FakeClock : public Clock {
int GetObserversCount() ABSL_LOCKS_EXCLUDED(mutex_);
void Reset() ABSL_LOCKS_EXCLUDED(mutex_);
private:
mutable absl::Mutex mutex_;
absl::Time now_ ABSL_GUARDED_BY(mutex_);
+12
View File
@@ -35,6 +35,18 @@ TEST(FakeClock, TestFastForward) {
EXPECT_EQ(clock.GetObserversCount(), 0);
}
TEST(FakeClock, TestReset) {
FakeClock clock;
int count = 0;
auto observer = [&count]() { count++; };
clock.AddObserver("test", observer);
clock.FastForward(absl::Nanoseconds(1500));
EXPECT_EQ(count, 1);
EXPECT_EQ(clock.GetObserversCount(), 1);
clock.Reset();
EXPECT_EQ(clock.GetObserversCount(), 0);
}
TEST(FakeClock, TestObserver) {
FakeClock clock;
int count = 0;
+70 -42
View File
@@ -1,4 +1,4 @@
// Copyright 2021 Google LLC
// Copyright 2021-2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -18,82 +18,110 @@
#include <string>
#include <utility>
#include "absl/functional/any_invocable.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "internal/platform/logging.h"
#include "internal/platform/mutex_lock.h"
namespace nearby {
FakeTimer::FakeTimer(FakeClock* clock) : clock_(clock) {
id_ = std::to_string(absl::ToUnixNanos(absl::Now()));
clock_->AddObserver(id_, [this]() { ClockUpdated(); });
}
FakeTimer::FakeTimer(FakeClock* clock) : clock_(clock) {}
FakeTimer::~FakeTimer() { clock_->RemoveObserver(id_); }
FakeTimer::~FakeTimer() { Stop(); }
bool FakeTimer::Start(int delay, int period,
absl::AnyInvocable<void()> callback) {
if (is_started_ || delay < 0 || period < 0) {
return false;
}
delay_ = delay;
period_ = period;
callback_ = std::move(callback);
start_time_ = clock_->Now();
fired_count_ = 0;
is_started_ = true;
return true;
MutexLock lock(&mutex_);
return InternalStart(delay, period, std::move(callback));
}
bool FakeTimer::Stop() {
is_started_ = false;
return true;
MutexLock lock(&mutex_);
return InternalStop();
}
bool FakeTimer::IsRunning() { return is_started_; }
bool FakeTimer::IsRunning() {
MutexLock lock(&mutex_);
return !timer_data_.id.empty();
}
void FakeTimer::ClockUpdated() {
if (!is_started_) {
MutexLock lock(&mutex_);
TimerData timer_data = timer_data_;
if (timer_data.id.empty()) {
return;
}
absl::Time now = clock_->Now();
int64_t duration = absl::ToInt64Milliseconds(now - start_time_);
FakeClock* clock = clock_;
// The timer may be released during callback, save period and delay to avoid
// access exception.
int period = period_;
int delay = delay_;
if (duration >= delay_ && fired_count_ == 0) {
++fired_count_;
if (callback_ != nullptr) {
callback_();
if (!timer_data.is_delay_called &&
timer_data.last_time == timer_data.create_time &&
timer_data.last_time + absl::Milliseconds(timer_data.delay) <= now) {
timer_data.callback();
if (timer_data.id == timer_data_.id) {
timer_data.is_delay_called = true;
timer_data.last_time =
timer_data.last_time + absl::Milliseconds(timer_data.delay);
timer_data_ = timer_data;
}
}
if (period == 0 || duration < delay ||
((clock_ != nullptr) && (clock_ != clock))) {
if (timer_data.period == 0 || timer_data.id != timer_data_.id) {
// timer is changed during callback.
return;
}
int count = (duration - delay) / period;
int should_fire_count = count - fired_count_ + 1;
for (int i = 0; i < should_fire_count; ++i) {
++fired_count_;
if (callback_ != nullptr) {
callback_();
timer_data_ = timer_data;
while (timer_data.last_time + absl::Milliseconds(timer_data.period) <= now) {
timer_data.callback();
if (timer_data.id == timer_data_.id) {
timer_data.last_time += absl::Milliseconds(timer_data.period);
} else {
return;
}
}
timer_data_ = timer_data;
}
bool FakeTimer::FireNow() {
if (IsRunning() && callback_) {
callback_();
if (IsRunning()) {
timer_data_.callback();
return true;
}
return false;
}
bool FakeTimer::InternalStart(int delay, int period,
absl::AnyInvocable<void()> callback) {
if (delay < 0 || period < 0 || callback == nullptr) {
return false;
}
if (!timer_data_.id.empty()) {
NEARBY_LOGS(ERROR) << __func__ << ": timer is already running";
return false;
}
timer_data_.id = std::to_string(absl::ToUnixNanos(absl::Now()));
timer_data_.delay = delay;
timer_data_.period = period;
callback_ = std::move(callback);
timer_data_.callback = [&]() { callback_(); };
timer_data_.create_time = clock_->Now();
timer_data_.last_time = timer_data_.create_time;
clock_->AddObserver(timer_data_.id, [this]() { ClockUpdated(); });
return true;
}
bool FakeTimer::InternalStop() {
if (timer_data_.id.empty()) {
return true;
}
clock_->RemoveObserver(timer_data_.id);
timer_data_ = {};
return true;
}
} // namespace nearby
+19 -9
View File
@@ -1,4 +1,4 @@
// Copyright 2021 Google LLC
// Copyright 2021-2023 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
@@ -17,6 +17,7 @@
#include <string>
#include "internal/platform/mutex.h"
#include "internal/platform/timer.h"
#include "internal/test/fake_clock.h"
@@ -35,16 +36,25 @@ class FakeTimer : public Timer {
bool FireNow() override;
private:
void ClockUpdated();
struct TimerData {
std::string id;
int delay;
int period;
bool is_delay_called = false;
absl::Time create_time;
absl::Time last_time;
std::function<void()> callback;
};
std::string id_;
int delay_ = 0;
int period_ = 0;
int fired_count_ = 0;
absl::Time start_time_;
bool is_started_ = false;
absl::AnyInvocable<void()> callback_;
void ClockUpdated();
bool InternalStart(int delay, int period,
absl::AnyInvocable<void()> callback);
bool InternalStop();
mutable RecursiveMutex mutex_;
FakeClock* clock_ = nullptr;
TimerData timer_data_;
absl::AnyInvocable<void()> callback_ = nullptr;
};
} // namespace nearby
+24 -3
View File
@@ -14,10 +14,11 @@
#include "internal/test/fake_timer.h"
#include "gmock/gmock.h"
#include "protobuf-matchers/protocol-buffer-matchers.h"
#include "gtest/gtest.h"
#include "absl/time/clock.h"
#include "absl/time/time.h"
#include "internal/platform/logging.h"
#include "internal/test/fake_task_runner.h"
namespace nearby {
namespace {
@@ -105,10 +106,10 @@ TEST(FakeTimer, TestTimerDestructor) {
FakeClock clock;
{
FakeTimer timer(&clock);
EXPECT_EQ(clock.GetObserversCount(), 1);
int count = 0;
auto callback = [&count]() { ++count; };
timer.Start(100, 0, callback);
EXPECT_EQ(clock.GetObserversCount(), 1);
EXPECT_TRUE(timer.IsRunning());
EXPECT_EQ(count, 0);
EXPECT_TRUE(timer.Stop());
@@ -160,5 +161,25 @@ TEST(FakeTimer, StartTimerInTimerProc) {
EXPECT_EQ(count, 2);
}
TEST(FakeTimer, WaitForRunningTask) {
bool finish = false;
FakeClock clock;
FakeTimer timer1(&clock);
FakeTaskRunner task_runner{&clock, 1};
timer1.Start(50, 0, [&]() {
absl::SleepFor(absl::Milliseconds(2000));
finish = true;
});
task_runner.PostTask([&]() {
absl::SleepFor(absl::Milliseconds(10));
timer1.Stop();
EXPECT_TRUE(finish);
});
clock.FastForward(absl::Milliseconds(50));
}
} // namespace
} // namespace nearby