dcsctp: Convert timers to rtc::TimeDelta

With this, the code base should be mostly converted from using
DurationMs to rtc::TimeDelta, and the work can continue to replace
TimeMs with rtc::Timestamp.

Bug: webrtc:15593
Change-Id: I083fee6eccb173efc0232bb8d46e2554a5fbee5b
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/326161
Reviewed-by: Florent Castelli <orphis@webrtc.org>
Commit-Queue: Victor Boivie <boivie@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#41101}
This commit is contained in:
Victor Boivie 2023-10-26 16:24:30 +02:00 committed by WebRTC LUCI CQ
parent 644025c51f
commit 4397482d71
17 changed files with 211 additions and 189 deletions

View File

@ -25,6 +25,7 @@
namespace dcsctp { namespace dcsctp {
namespace { namespace {
using ::webrtc::TimeDelta;
using ::testing::ElementsAre; using ::testing::ElementsAre;
using ::testing::IsEmpty; using ::testing::IsEmpty;
using ::testing::SizeIs; using ::testing::SizeIs;
@ -42,8 +43,8 @@ class DataTrackerTest : public testing::Test {
}), }),
timer_(timer_manager_.CreateTimer( timer_(timer_manager_.CreateTimer(
"test/delayed_ack", "test/delayed_ack",
[]() { return DurationMs(0); }, []() { return TimeDelta::Zero(); },
TimerOptions(DurationMs(0)))), TimerOptions(TimeDelta::Zero()))),
tracker_( tracker_(
std::make_unique<DataTracker>("log: ", timer_.get(), kInitialTSN)) { std::make_unique<DataTracker>("log: ", timer_.get(), kInitialTSN)) {
} }

View File

@ -11,6 +11,7 @@ import("../../../webrtc.gni")
rtc_source_set("context") { rtc_source_set("context") {
sources = [ "context.h" ] sources = [ "context.h" ]
deps = [ deps = [
"../../../api/units:time_delta",
"../common:internal_types", "../common:internal_types",
"../packet:sctp_packet", "../packet:sctp_packet",
"../public:socket", "../public:socket",
@ -24,6 +25,7 @@ rtc_library("heartbeat_handler") {
":context", ":context",
"../../../api:array_view", "../../../api:array_view",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../api/units:time_delta",
"../../../rtc_base:logging", "../../../rtc_base:logging",
"../packet:bounded_io", "../packet:bounded_io",
"../packet:chunk", "../packet:chunk",
@ -48,6 +50,7 @@ rtc_library("stream_reset_handler") {
deps = [ deps = [
":context", ":context",
"../../../api:array_view", "../../../api:array_view",
"../../../api/units:time_delta",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../rtc_base:logging", "../../../rtc_base:logging",
"../../../rtc_base/containers:flat_set", "../../../rtc_base/containers:flat_set",
@ -96,6 +99,7 @@ rtc_library("transmission_control_block") {
":packet_sender", ":packet_sender",
":stream_reset_handler", ":stream_reset_handler",
"../../../api:array_view", "../../../api:array_view",
"../../../api/units:time_delta",
"../../../api/task_queue:task_queue", "../../../api/task_queue:task_queue",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../rtc_base:logging", "../../../rtc_base:logging",

View File

@ -13,6 +13,7 @@
#include <cstdint> #include <cstdint>
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/common/internal_types.h" #include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/sctp_packet.h" #include "net/dcsctp/packet/sctp_packet.h"
#include "net/dcsctp/public/dcsctp_socket.h" #include "net/dcsctp/public/dcsctp_socket.h"

View File

@ -82,6 +82,7 @@
namespace dcsctp { namespace dcsctp {
namespace { namespace {
using ::webrtc::TimeDelta;
// https://tools.ietf.org/html/rfc4960#section-5.1 // https://tools.ietf.org/html/rfc4960#section-5.1
constexpr uint32_t kMinVerificationTag = 1; constexpr uint32_t kMinVerificationTag = 1;
@ -187,19 +188,19 @@ DcSctpSocket::DcSctpSocket(absl::string_view log_prefix,
t1_init_(timer_manager_.CreateTimer( t1_init_(timer_manager_.CreateTimer(
"t1-init", "t1-init",
absl::bind_front(&DcSctpSocket::OnInitTimerExpiry, this), absl::bind_front(&DcSctpSocket::OnInitTimerExpiry, this),
TimerOptions(options.t1_init_timeout, TimerOptions(options.t1_init_timeout.ToTimeDelta(),
TimerBackoffAlgorithm::kExponential, TimerBackoffAlgorithm::kExponential,
options.max_init_retransmits))), options.max_init_retransmits))),
t1_cookie_(timer_manager_.CreateTimer( t1_cookie_(timer_manager_.CreateTimer(
"t1-cookie", "t1-cookie",
absl::bind_front(&DcSctpSocket::OnCookieTimerExpiry, this), absl::bind_front(&DcSctpSocket::OnCookieTimerExpiry, this),
TimerOptions(options.t1_cookie_timeout, TimerOptions(options.t1_cookie_timeout.ToTimeDelta(),
TimerBackoffAlgorithm::kExponential, TimerBackoffAlgorithm::kExponential,
options.max_init_retransmits))), options.max_init_retransmits))),
t2_shutdown_(timer_manager_.CreateTimer( t2_shutdown_(timer_manager_.CreateTimer(
"t2-shutdown", "t2-shutdown",
absl::bind_front(&DcSctpSocket::OnShutdownTimerExpiry, this), absl::bind_front(&DcSctpSocket::OnShutdownTimerExpiry, this),
TimerOptions(options.t2_shutdown_timeout, TimerOptions(options.t2_shutdown_timeout.ToTimeDelta(),
TimerBackoffAlgorithm::kExponential, TimerBackoffAlgorithm::kExponential,
options.max_retransmissions))), options.max_retransmissions))),
packet_sender_(callbacks_, packet_sender_(callbacks_,
@ -631,7 +632,7 @@ void DcSctpSocket::MaybeSendShutdownOnPacketReceived(const SctpPacket& packet) {
// respond to each received packet containing one or more DATA chunks with // respond to each received packet containing one or more DATA chunks with
// a SHUTDOWN chunk and restart the T2-shutdown timer."" // a SHUTDOWN chunk and restart the T2-shutdown timer.""
SendShutdown(); SendShutdown();
t2_shutdown_->set_duration(DurationMs(tcb_->current_rto())); t2_shutdown_->set_duration(tcb_->current_rto());
t2_shutdown_->Start(); t2_shutdown_->Start();
} }
} }
@ -921,7 +922,7 @@ bool DcSctpSocket::HandleUnrecognizedChunk(
return continue_processing; return continue_processing;
} }
DurationMs DcSctpSocket::OnInitTimerExpiry() { TimeDelta DcSctpSocket::OnInitTimerExpiry() {
RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t1_init_->name() RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t1_init_->name()
<< " has expired: " << t1_init_->expiration_count() << " has expired: " << t1_init_->expiration_count()
<< "/" << t1_init_->options().max_restarts.value_or(-1); << "/" << t1_init_->options().max_restarts.value_or(-1);
@ -933,10 +934,10 @@ DurationMs DcSctpSocket::OnInitTimerExpiry() {
InternalClose(ErrorKind::kTooManyRetries, "No INIT_ACK received"); InternalClose(ErrorKind::kTooManyRetries, "No INIT_ACK received");
} }
RTC_DCHECK(IsConsistent()); RTC_DCHECK(IsConsistent());
return DurationMs(0); return TimeDelta::Zero();
} }
DurationMs DcSctpSocket::OnCookieTimerExpiry() { TimeDelta DcSctpSocket::OnCookieTimerExpiry() {
// https://tools.ietf.org/html/rfc4960#section-4 // https://tools.ietf.org/html/rfc4960#section-4
// "If the T1-cookie timer expires, the endpoint MUST retransmit COOKIE // "If the T1-cookie timer expires, the endpoint MUST retransmit COOKIE
// ECHO and restart the T1-cookie timer without changing state. This MUST // ECHO and restart the T1-cookie timer without changing state. This MUST
@ -957,10 +958,10 @@ DurationMs DcSctpSocket::OnCookieTimerExpiry() {
} }
RTC_DCHECK(IsConsistent()); RTC_DCHECK(IsConsistent());
return DurationMs(0); return TimeDelta::Zero();
} }
DurationMs DcSctpSocket::OnShutdownTimerExpiry() { TimeDelta DcSctpSocket::OnShutdownTimerExpiry() {
RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t2_shutdown_->name() RTC_DLOG(LS_VERBOSE) << log_prefix() << "Timer " << t2_shutdown_->name()
<< " has expired: " << t2_shutdown_->expiration_count() << " has expired: " << t2_shutdown_->expiration_count()
<< "/" << "/"
@ -980,7 +981,7 @@ DurationMs DcSctpSocket::OnShutdownTimerExpiry() {
InternalClose(ErrorKind::kTooManyRetries, "No SHUTDOWN_ACK received"); InternalClose(ErrorKind::kTooManyRetries, "No SHUTDOWN_ACK received");
RTC_DCHECK(IsConsistent()); RTC_DCHECK(IsConsistent());
return DurationMs(0); return TimeDelta::Zero();
} }
// https://tools.ietf.org/html/rfc4960#section-9.2 // https://tools.ietf.org/html/rfc4960#section-9.2
@ -988,7 +989,7 @@ DurationMs DcSctpSocket::OnShutdownTimerExpiry() {
// updated last sequential TSN received from its peer." // updated last sequential TSN received from its peer."
SendShutdown(); SendShutdown();
RTC_DCHECK(IsConsistent()); RTC_DCHECK(IsConsistent());
return DurationMs(tcb_->current_rto()); return tcb_->current_rto();
} }
void DcSctpSocket::OnSentPacket(rtc::ArrayView<const uint8_t> packet, void DcSctpSocket::OnSentPacket(rtc::ArrayView<const uint8_t> packet,
@ -1731,7 +1732,7 @@ void DcSctpSocket::MaybeSendShutdownOrAck() {
// state."" // state.""
SendShutdown(); SendShutdown();
t2_shutdown_->set_duration(DurationMs(tcb_->current_rto())); t2_shutdown_->set_duration(tcb_->current_rto());
t2_shutdown_->Start(); t2_shutdown_->Start();
SetState(State::kShutdownSent, "No more outstanding data"); SetState(State::kShutdownSent, "No more outstanding data");
} else if (state_ == State::kShutdownReceived) { } else if (state_ == State::kShutdownReceived) {
@ -1754,7 +1755,7 @@ void DcSctpSocket::SendShutdown() {
void DcSctpSocket::SendShutdownAck() { void DcSctpSocket::SendShutdownAck() {
packet_sender_.Send(tcb_->PacketBuilder().Add(ShutdownAckChunk())); packet_sender_.Send(tcb_->PacketBuilder().Add(ShutdownAckChunk()));
t2_shutdown_->set_duration(DurationMs(tcb_->current_rto())); t2_shutdown_->set_duration(tcb_->current_rto());
t2_shutdown_->Start(); t2_shutdown_->Start();
} }

View File

@ -155,9 +155,9 @@ class DcSctpSocket : public DcSctpSocketInterface {
// Closes the association, because of too many retransmission errors. // Closes the association, because of too many retransmission errors.
void CloseConnectionBecauseOfTooManyTransmissionErrors(); void CloseConnectionBecauseOfTooManyTransmissionErrors();
// Timer expiration handlers // Timer expiration handlers
DurationMs OnInitTimerExpiry(); webrtc::TimeDelta OnInitTimerExpiry();
DurationMs OnCookieTimerExpiry(); webrtc::TimeDelta OnCookieTimerExpiry();
DurationMs OnShutdownTimerExpiry(); webrtc::TimeDelta OnShutdownTimerExpiry();
void OnSentPacket(rtc::ArrayView<const uint8_t> packet, void OnSentPacket(rtc::ArrayView<const uint8_t> packet,
SendPacketStatus status); SendPacketStatus status);
// Sends SHUTDOWN or SHUTDOWN-ACK if the socket is shutting down and if all // Sends SHUTDOWN or SHUTDOWN-ACK if the socket is shutting down and if all

View File

@ -21,6 +21,7 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/array_view.h" #include "api/array_view.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/packet/bounded_byte_reader.h" #include "net/dcsctp/packet/bounded_byte_reader.h"
#include "net/dcsctp/packet/bounded_byte_writer.h" #include "net/dcsctp/packet/bounded_byte_writer.h"
#include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h" #include "net/dcsctp/packet/chunk/heartbeat_ack_chunk.h"
@ -35,6 +36,7 @@
#include "rtc_base/logging.h" #include "rtc_base/logging.h"
namespace dcsctp { namespace dcsctp {
using ::webrtc::TimeDelta;
// This is stored (in serialized form) as HeartbeatInfoParameter sent in // This is stored (in serialized form) as HeartbeatInfoParameter sent in
// HeartbeatRequestChunk and received back in HeartbeatAckChunk. It should be // HeartbeatRequestChunk and received back in HeartbeatAckChunk. It should be
@ -97,12 +99,12 @@ HeartbeatHandler::HeartbeatHandler(absl::string_view log_prefix,
interval_timer_(timer_manager_->CreateTimer( interval_timer_(timer_manager_->CreateTimer(
"heartbeat-interval", "heartbeat-interval",
absl::bind_front(&HeartbeatHandler::OnIntervalTimerExpiry, this), absl::bind_front(&HeartbeatHandler::OnIntervalTimerExpiry, this),
TimerOptions(DurationMs(interval_duration_), TimerOptions(interval_duration_,
TimerBackoffAlgorithm::kFixed))), TimerBackoffAlgorithm::kFixed))),
timeout_timer_(timer_manager_->CreateTimer( timeout_timer_(timer_manager_->CreateTimer(
"heartbeat-timeout", "heartbeat-timeout",
absl::bind_front(&HeartbeatHandler::OnTimeoutTimerExpiry, this), absl::bind_front(&HeartbeatHandler::OnTimeoutTimerExpiry, this),
TimerOptions(options.rto_initial, TimerOptions(options.rto_initial.ToTimeDelta(),
TimerBackoffAlgorithm::kExponential, TimerBackoffAlgorithm::kExponential,
/*max_restarts=*/0))) { /*max_restarts=*/0))) {
// The interval timer must always be running as long as the association is up. // The interval timer must always be running as long as the association is up.
@ -119,9 +121,9 @@ void HeartbeatHandler::RestartTimer() {
// The RTT should be used, but it's not easy accessible. The RTO will // The RTT should be used, but it's not easy accessible. The RTO will
// suffice. // suffice.
interval_timer_->set_duration( interval_timer_->set_duration(
DurationMs(interval_duration_ + ctx_->current_rto())); interval_duration_ + ctx_->current_rto());
} else { } else {
interval_timer_->set_duration(DurationMs(interval_duration_)); interval_timer_->set_duration(interval_duration_);
} }
interval_timer_->Start(); interval_timer_->Start();
@ -166,13 +168,13 @@ void HeartbeatHandler::HandleHeartbeatAck(HeartbeatAckChunk chunk) {
ctx_->ClearTxErrorCounter(); ctx_->ClearTxErrorCounter();
} }
DurationMs HeartbeatHandler::OnIntervalTimerExpiry() { TimeDelta HeartbeatHandler::OnIntervalTimerExpiry() {
if (ctx_->is_connection_established()) { if (ctx_->is_connection_established()) {
HeartbeatInfo info(ctx_->callbacks().TimeMillis()); HeartbeatInfo info(ctx_->callbacks().TimeMillis());
timeout_timer_->set_duration(DurationMs(ctx_->current_rto())); timeout_timer_->set_duration(ctx_->current_rto());
timeout_timer_->Start(); timeout_timer_->Start();
RTC_DLOG(LS_INFO) << log_prefix_ << "Sending HEARTBEAT with timeout " RTC_DLOG(LS_INFO) << log_prefix_ << "Sending HEARTBEAT with timeout "
<< *timeout_timer_->duration(); << webrtc::ToString(timeout_timer_->duration());
Parameters parameters = Parameters::Builder() Parameters parameters = Parameters::Builder()
.Add(HeartbeatInfoParameter(info.Serialize())) .Add(HeartbeatInfoParameter(info.Serialize()))
@ -185,14 +187,14 @@ DurationMs HeartbeatHandler::OnIntervalTimerExpiry() {
<< log_prefix_ << log_prefix_
<< "Will not send HEARTBEAT when connection not established"; << "Will not send HEARTBEAT when connection not established";
} }
return DurationMs(0); return TimeDelta::Zero();
} }
DurationMs HeartbeatHandler::OnTimeoutTimerExpiry() { TimeDelta HeartbeatHandler::OnTimeoutTimerExpiry() {
// Note that the timeout timer is not restarted. It will be started again when // Note that the timeout timer is not restarted. It will be started again when
// the interval timer expires. // the interval timer expires.
RTC_DCHECK(!timeout_timer_->is_running()); RTC_DCHECK(!timeout_timer_->is_running());
ctx_->IncrementTxErrorCounter("HEARTBEAT timeout"); ctx_->IncrementTxErrorCounter("HEARTBEAT timeout");
return DurationMs(0); return TimeDelta::Zero();
} }
} // namespace dcsctp } // namespace dcsctp

View File

@ -50,8 +50,8 @@ class HeartbeatHandler {
void HandleHeartbeatAck(HeartbeatAckChunk chunk); void HandleHeartbeatAck(HeartbeatAckChunk chunk);
private: private:
DurationMs OnIntervalTimerExpiry(); webrtc::TimeDelta OnIntervalTimerExpiry();
DurationMs OnTimeoutTimerExpiry(); webrtc::TimeDelta OnTimeoutTimerExpiry();
const absl::string_view log_prefix_; const absl::string_view log_prefix_;
Context* ctx_; Context* ctx_;

View File

@ -16,6 +16,7 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/array_view.h" #include "api/array_view.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/common/internal_types.h" #include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/common/str_join.h" #include "net/dcsctp/common/str_join.h"
#include "net/dcsctp/packet/chunk/reconfig_chunk.h" #include "net/dcsctp/packet/chunk/reconfig_chunk.h"
@ -38,6 +39,7 @@
namespace dcsctp { namespace dcsctp {
namespace { namespace {
using ::webrtc::TimeDelta;
using ResponseResult = ReconfigurationResponseParameter::Result; using ResponseResult = ReconfigurationResponseParameter::Result;
bool DescriptorsAre(const std::vector<ParameterDescriptor>& c, bool DescriptorsAre(const std::vector<ParameterDescriptor>& c,
@ -277,7 +279,7 @@ void StreamResetHandler::HandleResponse(const ParameterDescriptor& descriptor) {
}); });
// Force this request to be sent again, but with new req_seq_nbr. // Force this request to be sent again, but with new req_seq_nbr.
current_request_->PrepareRetransmission(); current_request_->PrepareRetransmission();
reconfig_timer_->set_duration(DurationMs(ctx_->current_rto())); reconfig_timer_->set_duration(ctx_->current_rto());
reconfig_timer_->Start(); reconfig_timer_->Start();
break; break;
case ResponseResult::kErrorRequestAlreadyInProgress: case ResponseResult::kErrorRequestAlreadyInProgress:
@ -312,7 +314,7 @@ absl::optional<ReConfigChunk> StreamResetHandler::MakeStreamResetRequest() {
current_request_.emplace(retransmission_queue_->last_assigned_tsn(), current_request_.emplace(retransmission_queue_->last_assigned_tsn(),
retransmission_queue_->BeginResetStreams()); retransmission_queue_->BeginResetStreams());
reconfig_timer_->set_duration(DurationMs(ctx_->current_rto())); reconfig_timer_->set_duration(ctx_->current_rto());
reconfig_timer_->Start(); reconfig_timer_->Start();
return MakeReconfigChunk(); return MakeReconfigChunk();
} }
@ -347,13 +349,13 @@ void StreamResetHandler::ResetStreams(
} }
} }
DurationMs StreamResetHandler::OnReconfigTimerExpiry() { TimeDelta StreamResetHandler::OnReconfigTimerExpiry() {
if (current_request_->has_been_sent()) { if (current_request_->has_been_sent()) {
// There is an outstanding request, which timed out while waiting for a // There is an outstanding request, which timed out while waiting for a
// response. // response.
if (!ctx_->IncrementTxErrorCounter("RECONFIG timeout")) { if (!ctx_->IncrementTxErrorCounter("RECONFIG timeout")) {
// Timed out. The connection will close after processing the timers. // Timed out. The connection will close after processing the timers.
return DurationMs(0); return TimeDelta::Zero();
} }
} else { } else {
// There is no outstanding request, but there is a prepared one. This means // There is no outstanding request, but there is a prepared one. This means
@ -362,7 +364,7 @@ DurationMs StreamResetHandler::OnReconfigTimerExpiry() {
} }
ctx_->Send(ctx_->PacketBuilder().Add(MakeReconfigChunk())); ctx_->Send(ctx_->PacketBuilder().Add(MakeReconfigChunk()));
return DurationMs(ctx_->current_rto()); return ctx_->current_rto();
} }
HandoverReadinessStatus StreamResetHandler::GetHandoverReadiness() const { HandoverReadinessStatus StreamResetHandler::GetHandoverReadiness() const {

View File

@ -20,6 +20,7 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/array_view.h" #include "api/array_view.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/common/internal_types.h" #include "net/dcsctp/common/internal_types.h"
#include "net/dcsctp/packet/chunk/reconfig_chunk.h" #include "net/dcsctp/packet/chunk/reconfig_chunk.h"
#include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h" #include "net/dcsctp/packet/parameter/incoming_ssn_reset_request_parameter.h"
@ -80,7 +81,7 @@ class StreamResetHandler {
reconfig_timer_(timer_manager->CreateTimer( reconfig_timer_(timer_manager->CreateTimer(
"re-config", "re-config",
absl::bind_front(&StreamResetHandler::OnReconfigTimerExpiry, this), absl::bind_front(&StreamResetHandler::OnReconfigTimerExpiry, this),
TimerOptions(DurationMs(0)))), TimerOptions(webrtc::TimeDelta::Zero()))),
next_outgoing_req_seq_nbr_( next_outgoing_req_seq_nbr_(
handover_state handover_state
? ReconfigRequestSN(handover_state->tx.next_reset_req_sn) ? ReconfigRequestSN(handover_state->tx.next_reset_req_sn)
@ -211,7 +212,7 @@ class StreamResetHandler {
void HandleResponse(const ParameterDescriptor& descriptor); void HandleResponse(const ParameterDescriptor& descriptor);
// Expiration handler for the Reconfig timer. // Expiration handler for the Reconfig timer.
DurationMs OnReconfigTimerExpiry(); webrtc::TimeDelta OnReconfigTimerExpiry();
const absl::string_view log_prefix_; const absl::string_view log_prefix_;
Context* ctx_; Context* ctx_;

View File

@ -98,12 +98,12 @@ class StreamResetHandlerTest : public testing::Test {
}), }),
delayed_ack_timer_(timer_manager_.CreateTimer( delayed_ack_timer_(timer_manager_.CreateTimer(
"test/delayed_ack", "test/delayed_ack",
[]() { return DurationMs(0); }, []() { return TimeDelta::Zero(); },
TimerOptions(DurationMs(0)))), TimerOptions(TimeDelta::Zero()))),
t3_rtx_timer_(timer_manager_.CreateTimer( t3_rtx_timer_(timer_manager_.CreateTimer(
"test/t3_rtx", "test/t3_rtx",
[]() { return DurationMs(0); }, []() { return TimeDelta::Zero(); },
TimerOptions(DurationMs(0)))), TimerOptions(TimeDelta::Zero()))),
data_tracker_(std::make_unique<DataTracker>("log: ", data_tracker_(std::make_unique<DataTracker>("log: ",
delayed_ack_timer_.get(), delayed_ack_timer_.get(),
kPeerInitialTsn)), kPeerInitialTsn)),
@ -205,8 +205,8 @@ class StreamResetHandlerTest : public testing::Test {
std::make_unique<ReassemblyQueue>("log: ", kPeerInitialTsn, kArwnd); std::make_unique<ReassemblyQueue>("log: ", kPeerInitialTsn, kArwnd);
reasm_->RestoreFromState(state); reasm_->RestoreFromState(state);
retransmission_queue_ = std::make_unique<RetransmissionQueue>( retransmission_queue_ = std::make_unique<RetransmissionQueue>(
"", &callbacks_, kMyInitialTsn, kArwnd, producer_, "", &callbacks_, kMyInitialTsn, kArwnd, producer_, [](TimeDelta rtt) {},
[](TimeDelta rtt) {}, []() {}, *t3_rtx_timer_, DcSctpOptions(), []() {}, *t3_rtx_timer_, DcSctpOptions(),
/*supports_partial_reliability=*/true, /*supports_partial_reliability=*/true,
/*use_message_interleaving=*/false); /*use_message_interleaving=*/false);
retransmission_queue_->RestoreFromState(state); retransmission_queue_->RestoreFromState(state);

View File

@ -17,6 +17,7 @@
#include <vector> #include <vector>
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/packet/chunk/data_chunk.h" #include "net/dcsctp/packet/chunk/data_chunk.h"
#include "net/dcsctp/packet/chunk/forward_tsn_chunk.h" #include "net/dcsctp/packet/chunk/forward_tsn_chunk.h"
#include "net/dcsctp/packet/chunk/idata_chunk.h" #include "net/dcsctp/packet/chunk/idata_chunk.h"
@ -62,20 +63,20 @@ TransmissionControlBlock::TransmissionControlBlock(
t3_rtx_(timer_manager_.CreateTimer( t3_rtx_(timer_manager_.CreateTimer(
"t3-rtx", "t3-rtx",
absl::bind_front(&TransmissionControlBlock::OnRtxTimerExpiry, this), absl::bind_front(&TransmissionControlBlock::OnRtxTimerExpiry, this),
TimerOptions(options.rto_initial, TimerOptions(options.rto_initial.ToTimeDelta(),
TimerBackoffAlgorithm::kExponential, TimerBackoffAlgorithm::kExponential,
/*max_restarts=*/absl::nullopt, /*max_restarts=*/absl::nullopt,
options.max_timer_backoff_duration.has_value() options.max_timer_backoff_duration.has_value()
? *options.max_timer_backoff_duration ? options.max_timer_backoff_duration->ToTimeDelta()
: DurationMs::InfiniteDuration()))), : TimeDelta::PlusInfinity()))),
delayed_ack_timer_(timer_manager_.CreateTimer( delayed_ack_timer_(timer_manager_.CreateTimer(
"delayed-ack", "delayed-ack",
absl::bind_front(&TransmissionControlBlock::OnDelayedAckTimerExpiry, absl::bind_front(&TransmissionControlBlock::OnDelayedAckTimerExpiry,
this), this),
TimerOptions(options.delayed_ack_max_timeout, TimerOptions(options.delayed_ack_max_timeout.ToTimeDelta(),
TimerBackoffAlgorithm::kExponential, TimerBackoffAlgorithm::kExponential,
/*max_restarts=*/0, /*max_restarts=*/0,
/*max_backoff_duration=*/DurationMs::InfiniteDuration(), /*max_backoff_duration=*/TimeDelta::PlusInfinity(),
webrtc::TaskQueueBase::DelayPrecision::kHigh))), webrtc::TaskQueueBase::DelayPrecision::kHigh))),
my_verification_tag_(my_verification_tag), my_verification_tag_(my_verification_tag),
my_initial_tsn_(my_initial_tsn), my_initial_tsn_(my_initial_tsn),
@ -120,14 +121,14 @@ void TransmissionControlBlock::ObserveRTT(TimeDelta rtt) {
<< ", srtt=" << webrtc::ToString(rto_.srtt()) << ", srtt=" << webrtc::ToString(rto_.srtt())
<< ", rto=" << webrtc::ToString(rto_.rto()) << " (" << ", rto=" << webrtc::ToString(rto_.rto()) << " ("
<< webrtc::ToString(prev_rto) << ")"; << webrtc::ToString(prev_rto) << ")";
t3_rtx_->set_duration(DurationMs(rto_.rto())); t3_rtx_->set_duration(rto_.rto());
DurationMs delayed_ack_tmo = TimeDelta delayed_ack_tmo = std::min(
std::min(DurationMs(rto_.rto()) * 0.5, options_.delayed_ack_max_timeout); rto_.rto() * 0.5, options_.delayed_ack_max_timeout.ToTimeDelta());
delayed_ack_timer_->set_duration(delayed_ack_tmo); delayed_ack_timer_->set_duration(delayed_ack_tmo);
} }
DurationMs TransmissionControlBlock::OnRtxTimerExpiry() { TimeDelta TransmissionControlBlock::OnRtxTimerExpiry() {
TimeMs now = callbacks_.TimeMillis(); TimeMs now = callbacks_.TimeMillis();
RTC_DLOG(LS_INFO) << log_prefix_ << "Timer " << t3_rtx_->name() RTC_DLOG(LS_INFO) << log_prefix_ << "Timer " << t3_rtx_->name()
<< " has expired"; << " has expired";
@ -141,13 +142,13 @@ DurationMs TransmissionControlBlock::OnRtxTimerExpiry() {
SendBufferedPackets(now); SendBufferedPackets(now);
} }
} }
return DurationMs(0); return TimeDelta::Zero();
} }
DurationMs TransmissionControlBlock::OnDelayedAckTimerExpiry() { TimeDelta TransmissionControlBlock::OnDelayedAckTimerExpiry() {
data_tracker_.HandleDelayedAckTimerExpiry(); data_tracker_.HandleDelayedAckTimerExpiry();
MaybeSendSack(); MaybeSendSack();
return DurationMs(0); return TimeDelta::Zero();
} }
void TransmissionControlBlock::MaybeSendSack() { void TransmissionControlBlock::MaybeSendSack() {

View File

@ -149,9 +149,9 @@ class TransmissionControlBlock : public Context {
private: private:
// Will be called when the retransmission timer (t3-rtx) expires. // Will be called when the retransmission timer (t3-rtx) expires.
DurationMs OnRtxTimerExpiry(); webrtc::TimeDelta OnRtxTimerExpiry();
// Will be called when the delayed ack timer expires. // Will be called when the delayed ack timer expires.
DurationMs OnDelayedAckTimerExpiry(); webrtc::TimeDelta OnDelayedAckTimerExpiry();
const absl::string_view log_prefix_; const absl::string_view log_prefix_;
const DcSctpOptions options_; const DcSctpOptions options_;

View File

@ -12,6 +12,7 @@ rtc_library("timer") {
deps = [ deps = [
"../../../api:array_view", "../../../api:array_view",
"../../../api/task_queue:task_queue", "../../../api/task_queue:task_queue",
"../../../api/units:time_delta",
"../../../rtc_base:checks", "../../../rtc_base:checks",
"../../../rtc_base:strong_alias", "../../../rtc_base:strong_alias",
"../../../rtc_base/containers:flat_map", "../../../rtc_base/containers:flat_map",
@ -57,6 +58,7 @@ if (rtc_include_tests) {
":task_queue_timeout", ":task_queue_timeout",
":timer", ":timer",
"../../../api:array_view", "../../../api:array_view",
"../../../api/units:time_delta",
"../../../api/task_queue:task_queue", "../../../api/task_queue:task_queue",
"../../../api/task_queue/test:mock_task_queue_base", "../../../api/task_queue/test:mock_task_queue_base",
"../../../rtc_base:checks", "../../../rtc_base:checks",

View File

@ -22,21 +22,23 @@
namespace dcsctp { namespace dcsctp {
namespace { namespace {
using ::webrtc::TimeDelta;
TimeoutID MakeTimeoutId(TimerID timer_id, TimerGeneration generation) { TimeoutID MakeTimeoutId(TimerID timer_id, TimerGeneration generation) {
return TimeoutID(static_cast<uint64_t>(*timer_id) << 32 | *generation); return TimeoutID(static_cast<uint64_t>(*timer_id) << 32 | *generation);
} }
DurationMs GetBackoffDuration(const TimerOptions& options, TimeDelta GetBackoffDuration(const TimerOptions& options,
DurationMs base_duration, TimeDelta base_duration,
int expiration_count) { int expiration_count) {
switch (options.backoff_algorithm) { switch (options.backoff_algorithm) {
case TimerBackoffAlgorithm::kFixed: case TimerBackoffAlgorithm::kFixed:
return base_duration; return base_duration;
case TimerBackoffAlgorithm::kExponential: { case TimerBackoffAlgorithm::kExponential: {
DurationMs duration = base_duration; TimeDelta duration = base_duration;
while (expiration_count > 0 && duration < Timer::kMaxTimerDuration) { while (expiration_count > 0 && duration < Timer::kMaxTimerDuration) {
duration *= 2; duration = duration * 2;
--expiration_count; --expiration_count;
if (duration > options.max_backoff_duration) { if (duration > options.max_backoff_duration) {
@ -44,13 +46,13 @@ DurationMs GetBackoffDuration(const TimerOptions& options,
} }
} }
return DurationMs(std::min(duration, Timer::kMaxTimerDuration)); return TimeDelta(std::min(duration, Timer::kMaxTimerDuration));
} }
} }
} }
} // namespace } // namespace
constexpr DurationMs Timer::kMaxTimerDuration; constexpr TimeDelta Timer::kMaxTimerDuration;
Timer::Timer(TimerID id, Timer::Timer(TimerID id,
absl::string_view name, absl::string_view name,
@ -76,12 +78,12 @@ void Timer::Start() {
if (!is_running()) { if (!is_running()) {
is_running_ = true; is_running_ = true;
generation_ = TimerGeneration(*generation_ + 1); generation_ = TimerGeneration(*generation_ + 1);
timeout_->Start(duration_, MakeTimeoutId(id_, generation_)); timeout_->Start(DurationMs(duration_), MakeTimeoutId(id_, generation_));
} else { } else {
// Timer was running - stop and restart it, to make it expire in `duration_` // Timer was running - stop and restart it, to make it expire in `duration_`
// from now. // from now.
generation_ = TimerGeneration(*generation_ + 1); generation_ = TimerGeneration(*generation_ + 1);
timeout_->Restart(duration_, MakeTimeoutId(id_, generation_)); timeout_->Restart(DurationMs(duration_), MakeTimeoutId(id_, generation_));
} }
} }
@ -103,24 +105,24 @@ void Timer::Trigger(TimerGeneration generation) {
// timer. Note that it might be very quickly restarted again, if the // timer. Note that it might be very quickly restarted again, if the
// `on_expired_` callback returns a new duration. // `on_expired_` callback returns a new duration.
is_running_ = true; is_running_ = true;
DurationMs duration = TimeDelta duration =
GetBackoffDuration(options_, duration_, expiration_count_); GetBackoffDuration(options_, duration_, expiration_count_);
generation_ = TimerGeneration(*generation_ + 1); generation_ = TimerGeneration(*generation_ + 1);
timeout_->Start(duration, MakeTimeoutId(id_, generation_)); timeout_->Start(DurationMs(duration), MakeTimeoutId(id_, generation_));
} }
DurationMs new_duration = on_expired_(); TimeDelta new_duration = on_expired_();
RTC_DCHECK(new_duration != DurationMs::InfiniteDuration()); RTC_DCHECK(new_duration != TimeDelta::PlusInfinity());
if (new_duration > DurationMs(0) && new_duration != duration_) { if (new_duration > TimeDelta::Zero() && new_duration != duration_) {
duration_ = new_duration; duration_ = new_duration;
if (is_running_) { if (is_running_) {
// Restart it with new duration. // Restart it with new duration.
timeout_->Stop(); timeout_->Stop();
DurationMs duration = TimeDelta duration =
GetBackoffDuration(options_, duration_, expiration_count_); GetBackoffDuration(options_, duration_, expiration_count_);
generation_ = TimerGeneration(*generation_ + 1); generation_ = TimerGeneration(*generation_ + 1);
timeout_->Start(duration, MakeTimeoutId(id_, generation_)); timeout_->Start(DurationMs(duration), MakeTimeoutId(id_, generation_));
} }
} }
} }

View File

@ -22,6 +22,7 @@
#include "absl/strings/string_view.h" #include "absl/strings/string_view.h"
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/task_queue/task_queue_base.h" #include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/public/timeout.h" #include "net/dcsctp/public/timeout.h"
#include "rtc_base/strong_alias.h" #include "rtc_base/strong_alias.h"
@ -40,30 +41,31 @@ enum class TimerBackoffAlgorithm {
}; };
struct TimerOptions { struct TimerOptions {
explicit TimerOptions(DurationMs duration) explicit TimerOptions(webrtc::TimeDelta duration)
: TimerOptions(duration, TimerBackoffAlgorithm::kExponential) {} : TimerOptions(duration, TimerBackoffAlgorithm::kExponential) {}
TimerOptions(DurationMs duration, TimerBackoffAlgorithm backoff_algorithm) TimerOptions(webrtc::TimeDelta duration,
TimerBackoffAlgorithm backoff_algorithm)
: TimerOptions(duration, backoff_algorithm, absl::nullopt) {} : TimerOptions(duration, backoff_algorithm, absl::nullopt) {}
TimerOptions(DurationMs duration, TimerOptions(webrtc::TimeDelta duration,
TimerBackoffAlgorithm backoff_algorithm, TimerBackoffAlgorithm backoff_algorithm,
absl::optional<int> max_restarts) absl::optional<int> max_restarts)
: TimerOptions(duration, : TimerOptions(duration,
backoff_algorithm, backoff_algorithm,
max_restarts, max_restarts,
DurationMs::InfiniteDuration()) {} webrtc::TimeDelta::PlusInfinity()) {}
TimerOptions(DurationMs duration, TimerOptions(webrtc::TimeDelta duration,
TimerBackoffAlgorithm backoff_algorithm, TimerBackoffAlgorithm backoff_algorithm,
absl::optional<int> max_restarts, absl::optional<int> max_restarts,
DurationMs max_backoff_duration) webrtc::TimeDelta max_backoff_duration)
: TimerOptions(duration, : TimerOptions(duration,
backoff_algorithm, backoff_algorithm,
max_restarts, max_restarts,
max_backoff_duration, max_backoff_duration,
webrtc::TaskQueueBase::DelayPrecision::kLow) {} webrtc::TaskQueueBase::DelayPrecision::kLow) {}
TimerOptions(DurationMs duration, TimerOptions(webrtc::TimeDelta duration,
TimerBackoffAlgorithm backoff_algorithm, TimerBackoffAlgorithm backoff_algorithm,
absl::optional<int> max_restarts, absl::optional<int> max_restarts,
DurationMs max_backoff_duration, webrtc::TimeDelta max_backoff_duration,
webrtc::TaskQueueBase::DelayPrecision precision) webrtc::TaskQueueBase::DelayPrecision precision)
: duration(duration), : duration(duration),
backoff_algorithm(backoff_algorithm), backoff_algorithm(backoff_algorithm),
@ -72,7 +74,7 @@ struct TimerOptions {
precision(precision) {} precision(precision) {}
// The initial timer duration. Can be overridden with `set_duration`. // The initial timer duration. Can be overridden with `set_duration`.
const DurationMs duration; const webrtc::TimeDelta duration;
// If the duration should be increased (using exponential backoff) when it is // If the duration should be increased (using exponential backoff) when it is
// restarted. If not set, the same duration will be used. // restarted. If not set, the same duration will be used.
const TimerBackoffAlgorithm backoff_algorithm; const TimerBackoffAlgorithm backoff_algorithm;
@ -80,7 +82,7 @@ struct TimerOptions {
// or absl::nullopt if there is no limit. // or absl::nullopt if there is no limit.
const absl::optional<int> max_restarts; const absl::optional<int> max_restarts;
// The maximum timeout value for exponential backoff. // The maximum timeout value for exponential backoff.
const DurationMs max_backoff_duration; const webrtc::TimeDelta max_backoff_duration;
// The precision of the webrtc::TaskQueueBase used for scheduling. // The precision of the webrtc::TaskQueueBase used for scheduling.
const webrtc::TaskQueueBase::DelayPrecision precision; const webrtc::TaskQueueBase::DelayPrecision precision;
}; };
@ -100,13 +102,14 @@ struct TimerOptions {
class Timer { class Timer {
public: public:
// The maximum timer duration - one day. // The maximum timer duration - one day.
static constexpr DurationMs kMaxTimerDuration = DurationMs(24 * 3600 * 1000); static constexpr webrtc::TimeDelta kMaxTimerDuration =
webrtc::TimeDelta::Seconds(24 * 3600);
// When expired, the timer handler can optionally return a new non-zero // When expired, the timer handler can optionally return a new non-zero
// duration which will be set as `duration` and used as base duration when the // duration which will be set as `duration` and used as base duration when the
// timer is restarted and as input to the backoff algorithm. If zero is // timer is restarted and as input to the backoff algorithm. If zero is
// returned, the current duration is used. // returned, the current duration is used.
using OnExpired = std::function<DurationMs()>; using OnExpired = std::function<webrtc::TimeDelta()>;
// TimerManager will have pointers to these instances, so they must not move. // TimerManager will have pointers to these instances, so they must not move.
Timer(const Timer&) = delete; Timer(const Timer&) = delete;
@ -124,13 +127,13 @@ class Timer {
// Sets the base duration. The actual timer duration may be larger depending // Sets the base duration. The actual timer duration may be larger depending
// on the backoff algorithm. // on the backoff algorithm.
void set_duration(DurationMs duration) { void set_duration(webrtc::TimeDelta duration) {
duration_ = std::min(duration, kMaxTimerDuration); duration_ = std::min(duration, kMaxTimerDuration);
} }
// Retrieves the base duration. The actual timer duration may be larger // Retrieves the base duration. The actual timer duration may be larger
// depending on the backoff algorithm. // depending on the backoff algorithm.
DurationMs duration() const { return duration_; } webrtc::TimeDelta duration() const { return duration_; }
// Returns the number of times the timer has expired. // Returns the number of times the timer has expired.
int expiration_count() const { return expiration_count_; } int expiration_count() const { return expiration_count_; }
@ -168,7 +171,7 @@ class Timer {
const UnregisterHandler unregister_handler_; const UnregisterHandler unregister_handler_;
const std::unique_ptr<Timeout> timeout_; const std::unique_ptr<Timeout> timeout_;
DurationMs duration_; webrtc::TimeDelta duration_;
// Increased on each start, and is matched on Trigger, to avoid races. And by // Increased on each start, and is matched on Trigger, to avoid races. And by
// race, meaning that a timeout - which may be evaluated/expired on a // race, meaning that a timeout - which may be evaluated/expired on a

View File

@ -13,6 +13,7 @@
#include "absl/types/optional.h" #include "absl/types/optional.h"
#include "api/task_queue/task_queue_base.h" #include "api/task_queue/task_queue_base.h"
#include "api/units/time_delta.h"
#include "net/dcsctp/public/timeout.h" #include "net/dcsctp/public/timeout.h"
#include "net/dcsctp/timer/fake_timeout.h" #include "net/dcsctp/timer/fake_timeout.h"
#include "rtc_base/gunit.h" #include "rtc_base/gunit.h"
@ -21,6 +22,7 @@
namespace dcsctp { namespace dcsctp {
namespace { namespace {
using ::testing::Return; using ::testing::Return;
using ::webrtc::TimeDelta;
class TimerTest : public testing::Test { class TimerTest : public testing::Test {
protected: protected:
@ -29,11 +31,11 @@ class TimerTest : public testing::Test {
manager_([this](webrtc::TaskQueueBase::DelayPrecision precision) { manager_([this](webrtc::TaskQueueBase::DelayPrecision precision) {
return timeout_manager_.CreateTimeout(precision); return timeout_manager_.CreateTimeout(precision);
}) { }) {
ON_CALL(on_expired_, Call).WillByDefault(Return(DurationMs(0))); ON_CALL(on_expired_, Call).WillByDefault(Return(TimeDelta::Zero()));
} }
void AdvanceTimeAndRunTimers(DurationMs duration) { void AdvanceTimeAndRunTimers(TimeDelta duration) {
now_ = now_ + duration; now_ = now_ + DurationMs(duration);
for (;;) { for (;;) {
absl::optional<TimeoutID> timeout_id = absl::optional<TimeoutID> timeout_id =
@ -48,13 +50,13 @@ class TimerTest : public testing::Test {
TimeMs now_ = TimeMs(0); TimeMs now_ = TimeMs(0);
FakeTimeoutManager timeout_manager_; FakeTimeoutManager timeout_manager_;
TimerManager manager_; TimerManager manager_;
testing::MockFunction<DurationMs()> on_expired_; testing::MockFunction<TimeDelta()> on_expired_;
}; };
TEST_F(TimerTest, TimerIsInitiallyStopped) { TEST_F(TimerTest, TimerIsInitiallyStopped) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed));
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
} }
@ -62,50 +64,50 @@ TEST_F(TimerTest, TimerIsInitiallyStopped) {
TEST_F(TimerTest, TimerExpiresAtGivenTime) { TEST_F(TimerTest, TimerExpiresAtGivenTime) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
t1->Start(); t1->Start();
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
} }
TEST_F(TimerTest, TimerReschedulesAfterExpiredWithFixedBackoff) { TEST_F(TimerTest, TimerReschedulesAfterExpiredWithFixedBackoff) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
t1->Start(); t1->Start();
EXPECT_EQ(t1->expiration_count(), 0); EXPECT_EQ(t1->expiration_count(), 0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Fire first time // Fire first time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_EQ(t1->expiration_count(), 1); EXPECT_EQ(t1->expiration_count(), 1);
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Second time // Second time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_EQ(t1->expiration_count(), 2); EXPECT_EQ(t1->expiration_count(), 2);
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Third time // Third time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_EQ(t1->expiration_count(), 3); EXPECT_EQ(t1->expiration_count(), 3);
} }
@ -113,151 +115,151 @@ TEST_F(TimerTest, TimerReschedulesAfterExpiredWithFixedBackoff) {
TEST_F(TimerTest, TimerWithNoRestarts) { TEST_F(TimerTest, TimerWithNoRestarts) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed, TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed,
/*max_restart=*/0)); /*max_restart=*/0));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
t1->Start(); t1->Start();
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Fire first time // Fire first time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
// Second time - shouldn't fire // Second time - shouldn't fire
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(5000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(5));
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
} }
TEST_F(TimerTest, TimerWithOneRestart) { TEST_F(TimerTest, TimerWithOneRestart) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed, TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed,
/*max_restart=*/1)); /*max_restart=*/1));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
t1->Start(); t1->Start();
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Fire first time // Fire first time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Second time - max restart limit reached. // Second time - max restart limit reached.
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
// Third time - should not fire. // Third time - should not fire.
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(5000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(5));
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
} }
TEST_F(TimerTest, TimerWithTwoRestart) { TEST_F(TimerTest, TimerWithTwoRestart) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed, TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed,
/*max_restart=*/2)); /*max_restart=*/2));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
t1->Start(); t1->Start();
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Fire first time // Fire first time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Second time // Second time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Third time // Third time
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
} }
TEST_F(TimerTest, TimerWithExponentialBackoff) { TEST_F(TimerTest, TimerWithExponentialBackoff) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kExponential));
t1->Start(); t1->Start();
// Fire first time at 5 seconds // Fire first time at 5 seconds
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(5000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(5));
// Second time at 5*2^1 = 10 seconds later. // Second time at 5*2^1 = 10 seconds later.
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(9000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(9));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
// Third time at 5*2^2 = 20 seconds later. // Third time at 5*2^2 = 20 seconds later.
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(19000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(19));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
// Fourth time at 5*2^3 = 40 seconds later. // Fourth time at 5*2^3 = 40 seconds later.
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(39000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(39));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
} }
TEST_F(TimerTest, StartTimerWillStopAndStart) { TEST_F(TimerTest, StartTimerWillStopAndStart) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kExponential));
t1->Start(); t1->Start();
AdvanceTimeAndRunTimers(DurationMs(3000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(3));
t1->Start(); t1->Start();
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(2000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(2));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(3000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(3));
} }
TEST_F(TimerTest, ExpirationCounterWillResetIfStopped) { TEST_F(TimerTest, ExpirationCounterWillResetIfStopped) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kExponential));
t1->Start(); t1->Start();
// Fire first time at 5 seconds // Fire first time at 5 seconds
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(5000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(5));
EXPECT_EQ(t1->expiration_count(), 1); EXPECT_EQ(t1->expiration_count(), 1);
// Second time at 5*2^1 = 10 seconds later. // Second time at 5*2^1 = 10 seconds later.
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(9000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(9));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_EQ(t1->expiration_count(), 2); EXPECT_EQ(t1->expiration_count(), 2);
t1->Start(); t1->Start();
@ -265,79 +267,79 @@ TEST_F(TimerTest, ExpirationCounterWillResetIfStopped) {
// Third time at 5*2^0 = 5 seconds later. // Third time at 5*2^0 = 5 seconds later.
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_EQ(t1->expiration_count(), 1); EXPECT_EQ(t1->expiration_count(), 1);
} }
TEST_F(TimerTest, StopTimerWillMakeItNotExpire) { TEST_F(TimerTest, StopTimerWillMakeItNotExpire) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kExponential)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kExponential));
t1->Start(); t1->Start();
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
t1->Stop(); t1->Stop();
EXPECT_FALSE(t1->is_running()); EXPECT_FALSE(t1->is_running());
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
} }
TEST_F(TimerTest, ReturningNewDurationWhenExpired) { TEST_F(TimerTest, ReturningNewDurationWhenExpired) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(5000), TimerBackoffAlgorithm::kFixed)); TimerOptions(TimeDelta::Seconds(5), TimerBackoffAlgorithm::kFixed));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
t1->Start(); t1->Start();
EXPECT_EQ(t1->duration(), DurationMs(5000)); EXPECT_EQ(t1->duration(), TimeDelta::Seconds(5));
AdvanceTimeAndRunTimers(DurationMs(4000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(4));
// Fire first time // Fire first time
EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(2000))); EXPECT_CALL(on_expired_, Call).WillOnce(Return(TimeDelta::Seconds(2)));
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_EQ(t1->duration(), DurationMs(2000)); EXPECT_EQ(t1->duration(), TimeDelta::Seconds(2));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
// Second time // Second time
EXPECT_CALL(on_expired_, Call).WillOnce(Return(DurationMs(10000))); EXPECT_CALL(on_expired_, Call).WillOnce(Return(TimeDelta::Seconds(10)));
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_EQ(t1->duration(), DurationMs(10000)); EXPECT_EQ(t1->duration(), TimeDelta::Seconds(10));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(9000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(9));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
} }
TEST_F(TimerTest, TimersHaveMaximumDuration) { TEST_F(TimerTest, TimersHaveMaximumDuration) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential)); TimerOptions(TimeDelta::Seconds(1), TimerBackoffAlgorithm::kExponential));
t1->set_duration(DurationMs(2 * *Timer::kMaxTimerDuration)); t1->set_duration(2 * Timer::kMaxTimerDuration);
EXPECT_EQ(t1->duration(), Timer::kMaxTimerDuration); EXPECT_EQ(t1->duration(), Timer::kMaxTimerDuration);
} }
TEST_F(TimerTest, TimersHaveMaximumBackoffDuration) { TEST_F(TimerTest, TimersHaveMaximumBackoffDuration) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential)); TimerOptions(TimeDelta::Seconds(1), TimerBackoffAlgorithm::kExponential));
t1->Start(); t1->Start();
int max_exponent = static_cast<int>(log2(*Timer::kMaxTimerDuration / 1000)); int max_exponent = static_cast<int>(log2(Timer::kMaxTimerDuration.seconds()));
for (int i = 0; i < max_exponent; ++i) { for (int i = 0; i < max_exponent; ++i) {
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000 * (1 << i))); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1 * (1 << i)));
} }
// Reached the maximum duration. // Reached the maximum duration.
@ -357,73 +359,73 @@ TEST_F(TimerTest, TimersHaveMaximumBackoffDuration) {
TEST_F(TimerTest, TimerCanBeStartedFromWithinExpirationHandler) { TEST_F(TimerTest, TimerCanBeStartedFromWithinExpirationHandler) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kFixed)); TimerOptions(TimeDelta::Seconds(1), TimerBackoffAlgorithm::kFixed));
t1->Start(); t1->Start();
// Start a timer, but don't return any new duration in callback. // Start a timer, but don't return any new duration in callback.
EXPECT_CALL(on_expired_, Call).WillOnce([&]() { EXPECT_CALL(on_expired_, Call).WillOnce([&]() {
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
t1->set_duration(DurationMs(5000)); t1->set_duration(TimeDelta::Seconds(5));
t1->Start(); t1->Start();
return DurationMs(0); return TimeDelta::Zero();
}); });
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4999)); AdvanceTimeAndRunTimers(TimeDelta::Millis(4999));
// Start a timer, and return any new duration in callback. // Start a timer, and return any new duration in callback.
EXPECT_CALL(on_expired_, Call).WillOnce([&]() { EXPECT_CALL(on_expired_, Call).WillOnce([&]() {
EXPECT_TRUE(t1->is_running()); EXPECT_TRUE(t1->is_running());
t1->set_duration(DurationMs(5000)); t1->set_duration(TimeDelta::Seconds(5));
t1->Start(); t1->Start();
return DurationMs(8000); return TimeDelta::Seconds(8);
}); });
AdvanceTimeAndRunTimers(DurationMs(1)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1));
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(7999)); AdvanceTimeAndRunTimers(TimeDelta::Millis(7999));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1));
} }
TEST_F(TimerTest, DurationStaysWithinMaxTimerBackOffDuration) { TEST_F(TimerTest, DurationStaysWithinMaxTimerBackOffDuration) {
std::unique_ptr<Timer> t1 = manager_.CreateTimer( std::unique_ptr<Timer> t1 = manager_.CreateTimer(
"t1", on_expired_.AsStdFunction(), "t1", on_expired_.AsStdFunction(),
TimerOptions(DurationMs(1000), TimerBackoffAlgorithm::kExponential, TimerOptions(TimeDelta::Seconds(1), TimerBackoffAlgorithm::kExponential,
/*max_restarts=*/absl::nullopt, DurationMs(5000))); /*max_restarts=*/absl::nullopt, TimeDelta::Seconds(5)));
t1->Start(); t1->Start();
// Initial timeout, 1000 ms // Initial timeout, 1000 ms
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1000)); AdvanceTimeAndRunTimers(TimeDelta::Seconds(1));
// Exponential backoff -> 2000 ms // Exponential backoff -> 2000 ms
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(1999)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1999));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1));
// Exponential backoff -> 4000 ms // Exponential backoff -> 4000 ms
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(3999)); AdvanceTimeAndRunTimers(TimeDelta::Millis(3999));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1));
// Limited backoff -> 5000ms // Limited backoff -> 5000ms
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4999)); AdvanceTimeAndRunTimers(TimeDelta::Millis(4999));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1));
// ... where it plateaus // ... where it plateaus
EXPECT_CALL(on_expired_, Call).Times(0); EXPECT_CALL(on_expired_, Call).Times(0);
AdvanceTimeAndRunTimers(DurationMs(4999)); AdvanceTimeAndRunTimers(TimeDelta::Millis(4999));
EXPECT_CALL(on_expired_, Call).Times(1); EXPECT_CALL(on_expired_, Call).Times(1);
AdvanceTimeAndRunTimers(DurationMs(1)); AdvanceTimeAndRunTimers(TimeDelta::Millis(1));
} }
TEST(TimerManagerTest, TimerManagerPassesPrecisionToCreateTimeoutMethod) { TEST(TimerManagerTest, TimerManagerPassesPrecisionToCreateTimeoutMethod) {
@ -435,22 +437,22 @@ TEST(TimerManagerTest, TimerManagerPassesPrecisionToCreateTimeoutMethod) {
}); });
// Default TimerOptions. // Default TimerOptions.
manager.CreateTimer( manager.CreateTimer(
"test_timer", []() { return DurationMs(0); }, "test_timer", []() { return TimeDelta::Zero(); },
TimerOptions(DurationMs(123))); TimerOptions(TimeDelta::Millis(123)));
EXPECT_EQ(create_timer_precison, webrtc::TaskQueueBase::DelayPrecision::kLow); EXPECT_EQ(create_timer_precison, webrtc::TaskQueueBase::DelayPrecision::kLow);
// High precision TimerOptions. // High precision TimerOptions.
manager.CreateTimer( manager.CreateTimer(
"test_timer", []() { return DurationMs(0); }, "test_timer", []() { return TimeDelta::Zero(); },
TimerOptions(DurationMs(123), TimerBackoffAlgorithm::kExponential, TimerOptions(TimeDelta::Millis(123), TimerBackoffAlgorithm::kExponential,
absl::nullopt, DurationMs::InfiniteDuration(), absl::nullopt, TimeDelta::PlusInfinity(),
webrtc::TaskQueueBase::DelayPrecision::kHigh)); webrtc::TaskQueueBase::DelayPrecision::kHigh));
EXPECT_EQ(create_timer_precison, EXPECT_EQ(create_timer_precison,
webrtc::TaskQueueBase::DelayPrecision::kHigh); webrtc::TaskQueueBase::DelayPrecision::kHigh);
// Low precision TimerOptions. // Low precision TimerOptions.
manager.CreateTimer( manager.CreateTimer(
"test_timer", []() { return DurationMs(0); }, "test_timer", []() { return TimeDelta::Zero(); },
TimerOptions(DurationMs(123), TimerBackoffAlgorithm::kExponential, TimerOptions(TimeDelta::Millis(123), TimerBackoffAlgorithm::kExponential,
absl::nullopt, DurationMs::InfiniteDuration(), absl::nullopt, TimeDelta::PlusInfinity(),
webrtc::TaskQueueBase::DelayPrecision::kLow)); webrtc::TaskQueueBase::DelayPrecision::kLow));
EXPECT_EQ(create_timer_precison, webrtc::TaskQueueBase::DelayPrecision::kLow); EXPECT_EQ(create_timer_precison, webrtc::TaskQueueBase::DelayPrecision::kLow);
} }

View File

@ -75,8 +75,8 @@ class RetransmissionQueueTest : public testing::Test {
}), }),
timer_(timer_manager_.CreateTimer( timer_(timer_manager_.CreateTimer(
"test/t3_rtx", "test/t3_rtx",
[]() { return DurationMs(0); }, []() { return TimeDelta::Zero(); },
TimerOptions(options_.rto_initial))) {} TimerOptions(options_.rto_initial.ToTimeDelta()))) {}
std::function<SendQueue::DataToSend(TimeMs, size_t)> CreateChunk( std::function<SendQueue::DataToSend(TimeMs, size_t)> CreateChunk(
OutgoingMessageId message_id) { OutgoingMessageId message_id) {