1 /*
2 * Copyright (c) 2021 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #ifndef NET_DCSCTP_SOCKET_MOCK_DCSCTP_SOCKET_CALLBACKS_H_
11 #define NET_DCSCTP_SOCKET_MOCK_DCSCTP_SOCKET_CALLBACKS_H_
12
13 #include <cstdint>
14 #include <deque>
15 #include <memory>
16 #include <string>
17 #include <utility>
18 #include <vector>
19
20 #include "absl/strings/string_view.h"
21 #include "absl/types/optional.h"
22 #include "api/array_view.h"
23 #include "api/task_queue/task_queue_base.h"
24 #include "net/dcsctp/public/dcsctp_message.h"
25 #include "net/dcsctp/public/dcsctp_socket.h"
26 #include "net/dcsctp/public/timeout.h"
27 #include "net/dcsctp/public/types.h"
28 #include "net/dcsctp/timer/fake_timeout.h"
29 #include "rtc_base/logging.h"
30 #include "rtc_base/random.h"
31 #include "test/gmock.h"
32
33 namespace dcsctp {
34
35 namespace internal {
36 // It can be argued if a mocked random number generator should be deterministic
37 // or if it should be have as a "real" random number generator. In this
38 // implementation, each instantiation of `MockDcSctpSocketCallbacks` will have
39 // their `GetRandomInt` return different sequences, but each instantiation will
40 // always generate the same sequence of random numbers. This to make it easier
41 // to compare logs from tests, but still to let e.g. two different sockets (used
42 // in the same test) get different random numbers, so that they don't start e.g.
43 // on the same sequence number. While that isn't an issue in the protocol, it
44 // just makes debugging harder as the two sockets would look exactly the same.
45 //
46 // In a real implementation of `DcSctpSocketCallbacks` the random number
47 // generator backing `GetRandomInt` should be seeded externally and correctly.
GetUniqueSeed()48 inline int GetUniqueSeed() {
49 static int seed = 0;
50 return ++seed;
51 }
52 } // namespace internal
53
54 class MockDcSctpSocketCallbacks : public DcSctpSocketCallbacks {
55 public:
56 explicit MockDcSctpSocketCallbacks(absl::string_view name = "")
57 : log_prefix_(name.empty() ? "" : std::string(name) + ": "),
58 random_(internal::GetUniqueSeed()),
59 timeout_manager_([this]() { return now_; }) {
60 ON_CALL(*this, SendPacketWithStatus)
61 .WillByDefault([this](rtc::ArrayView<const uint8_t> data) {
62 sent_packets_.emplace_back(
63 std::vector<uint8_t>(data.begin(), data.end()));
64 return SendPacketStatus::kSuccess;
65 });
66 ON_CALL(*this, OnMessageReceived)
67 .WillByDefault([this](DcSctpMessage message) {
68 received_messages_.emplace_back(std::move(message));
69 });
70
71 ON_CALL(*this, OnError)
72 .WillByDefault([this](ErrorKind error, absl::string_view message) {
73 RTC_LOG(LS_WARNING)
74 << log_prefix_ << "Socket error: " << ToString(error) << "; "
75 << message;
76 });
77 ON_CALL(*this, OnAborted)
78 .WillByDefault([this](ErrorKind error, absl::string_view message) {
79 RTC_LOG(LS_WARNING)
80 << log_prefix_ << "Socket abort: " << ToString(error) << "; "
81 << message;
82 });
83 ON_CALL(*this, TimeMillis).WillByDefault([this]() { return now_; });
84 }
85
86 MOCK_METHOD(SendPacketStatus,
87 SendPacketWithStatus,
88 (rtc::ArrayView<const uint8_t> data),
89 (override));
90
CreateTimeout(webrtc::TaskQueueBase::DelayPrecision precision)91 std::unique_ptr<Timeout> CreateTimeout(
92 webrtc::TaskQueueBase::DelayPrecision precision) override {
93 // The fake timeout manager does not implement |precision|.
94 return timeout_manager_.CreateTimeout();
95 }
96
97 MOCK_METHOD(TimeMs, TimeMillis, (), (override));
GetRandomInt(uint32_t low,uint32_t high)98 uint32_t GetRandomInt(uint32_t low, uint32_t high) override {
99 return random_.Rand(low, high);
100 }
101
102 MOCK_METHOD(void, OnMessageReceived, (DcSctpMessage message), (override));
103 MOCK_METHOD(void,
104 OnError,
105 (ErrorKind error, absl::string_view message),
106 (override));
107 MOCK_METHOD(void,
108 OnAborted,
109 (ErrorKind error, absl::string_view message),
110 (override));
111 MOCK_METHOD(void, OnConnected, (), (override));
112 MOCK_METHOD(void, OnClosed, (), (override));
113 MOCK_METHOD(void, OnConnectionRestarted, (), (override));
114 MOCK_METHOD(void,
115 OnStreamsResetFailed,
116 (rtc::ArrayView<const StreamID> outgoing_streams,
117 absl::string_view reason),
118 (override));
119 MOCK_METHOD(void,
120 OnStreamsResetPerformed,
121 (rtc::ArrayView<const StreamID> outgoing_streams),
122 (override));
123 MOCK_METHOD(void,
124 OnIncomingStreamsReset,
125 (rtc::ArrayView<const StreamID> incoming_streams),
126 (override));
127 MOCK_METHOD(void, OnBufferedAmountLow, (StreamID stream_id), (override));
128 MOCK_METHOD(void, OnTotalBufferedAmountLow, (), (override));
129 MOCK_METHOD(void,
130 OnLifecycleMessageExpired,
131 (LifecycleId lifecycle_id, bool maybe_delivered),
132 (override));
133 MOCK_METHOD(void,
134 OnLifecycleMessageFullySent,
135 (LifecycleId lifecycle_id),
136 (override));
137 MOCK_METHOD(void,
138 OnLifecycleMessageDelivered,
139 (LifecycleId lifecycle_id),
140 (override));
141 MOCK_METHOD(void, OnLifecycleEnd, (LifecycleId lifecycle_id), (override));
142
HasPacket()143 bool HasPacket() const { return !sent_packets_.empty(); }
144
ConsumeSentPacket()145 std::vector<uint8_t> ConsumeSentPacket() {
146 if (sent_packets_.empty()) {
147 return {};
148 }
149 std::vector<uint8_t> ret = std::move(sent_packets_.front());
150 sent_packets_.pop_front();
151 return ret;
152 }
ConsumeReceivedMessage()153 absl::optional<DcSctpMessage> ConsumeReceivedMessage() {
154 if (received_messages_.empty()) {
155 return absl::nullopt;
156 }
157 DcSctpMessage ret = std::move(received_messages_.front());
158 received_messages_.pop_front();
159 return ret;
160 }
161
AdvanceTime(DurationMs duration_ms)162 void AdvanceTime(DurationMs duration_ms) { now_ = now_ + duration_ms; }
SetTime(TimeMs now)163 void SetTime(TimeMs now) { now_ = now; }
164
GetNextExpiredTimeout()165 absl::optional<TimeoutID> GetNextExpiredTimeout() {
166 return timeout_manager_.GetNextExpiredTimeout();
167 }
168
169 private:
170 const std::string log_prefix_;
171 TimeMs now_ = TimeMs(0);
172 webrtc::Random random_;
173 FakeTimeoutManager timeout_manager_;
174 std::deque<std::vector<uint8_t>> sent_packets_;
175 std::deque<DcSctpMessage> received_messages_;
176 };
177 } // namespace dcsctp
178
179 #endif // NET_DCSCTP_SOCKET_MOCK_DCSCTP_SOCKET_CALLBACKS_H_
180