blob: d45c99a42316b0bbd82017b4393813c315bf4316 [file] [log] [blame]
// Copyright 2023 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef QUICHE_QUIC_MOQT_TOOLS_MOQT_MOCK_VISITOR_H_
#define QUICHE_QUIC_MOQT_TOOLS_MOQT_MOCK_VISITOR_H_
#include <cstdint>
#include <memory>
#include <optional>
#include <utility>
#include <variant>
#include <vector>
#include "absl/status/status.h"
#include "absl/status/statusor.h"
#include "absl/strings/string_view.h"
#include "quiche/quic/core/quic_time.h"
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/quic/moqt/moqt_priority.h"
#include "quiche/quic/moqt/moqt_publisher.h"
#include "quiche/quic/moqt/moqt_session.h"
#include "quiche/quic/moqt/moqt_track.h"
#include "quiche/common/platform/api/quiche_test.h"
namespace moqt::test {
struct MockSessionCallbacks {
testing::MockFunction<void()> session_established_callback;
testing::MockFunction<void(absl::string_view)> goaway_received_callback;
testing::MockFunction<void(absl::string_view)> session_terminated_callback;
testing::MockFunction<void()> session_deleted_callback;
testing::MockFunction<std::optional<MoqtAnnounceErrorReason>(
const TrackNamespace&, std::optional<VersionSpecificParameters>)>
incoming_announce_callback;
testing::MockFunction<std::optional<MoqtSubscribeErrorReason>(
TrackNamespace, std::optional<VersionSpecificParameters>)>
incoming_subscribe_announces_callback;
MockSessionCallbacks() {
ON_CALL(incoming_announce_callback, Call(testing::_, testing::_))
.WillByDefault(DefaultIncomingAnnounceCallback);
ON_CALL(incoming_subscribe_announces_callback, Call(testing::_, testing::_))
.WillByDefault(DefaultIncomingSubscribeAnnouncesCallback);
}
MoqtSessionCallbacks AsSessionCallbacks() {
return MoqtSessionCallbacks{
session_established_callback.AsStdFunction(),
goaway_received_callback.AsStdFunction(),
session_terminated_callback.AsStdFunction(),
session_deleted_callback.AsStdFunction(),
incoming_announce_callback.AsStdFunction(),
incoming_subscribe_announces_callback.AsStdFunction()};
}
};
class MockTrackPublisher : public MoqtTrackPublisher {
public:
explicit MockTrackPublisher(FullTrackName name)
: track_name_(std::move(name)) {
ON_CALL(*this, GetDeliveryOrder())
.WillByDefault(testing::Return(MoqtDeliveryOrder::kAscending));
}
const FullTrackName& GetTrackName() const override { return track_name_; }
MOCK_METHOD(std::optional<PublishedObject>, GetCachedObject,
(Location sequence), (const, override));
MOCK_METHOD(std::vector<Location>, GetCachedObjectsInRange,
(Location start, Location end), (const, override));
MOCK_METHOD(void, AddObjectListener, (MoqtObjectListener * listener),
(override));
MOCK_METHOD(void, RemoveObjectListener, (MoqtObjectListener * listener),
(override));
MOCK_METHOD(absl::StatusOr<MoqtTrackStatusCode>, GetTrackStatus, (),
(const, override));
MOCK_METHOD(Location, GetLargestLocation, (), (const, override));
MOCK_METHOD(MoqtForwardingPreference, GetForwardingPreference, (),
(const, override));
MOCK_METHOD(MoqtPriority, GetPublisherPriority, (), (const, override));
MOCK_METHOD(MoqtDeliveryOrder, GetDeliveryOrder, (), (const, override));
MOCK_METHOD(std::unique_ptr<MoqtFetchTask>, Fetch,
(Location, uint64_t, std::optional<uint64_t>, MoqtDeliveryOrder),
(override));
private:
FullTrackName track_name_;
};
class MockSubscribeRemoteTrackVisitor : public SubscribeRemoteTrack::Visitor {
public:
MOCK_METHOD(void, OnReply,
(const FullTrackName& full_track_name,
std::optional<Location> largest_id,
std::optional<absl::string_view> error_reason_phrase),
(override));
MOCK_METHOD(void, OnCanAckObjects, (MoqtObjectAckFunction ack_function),
(override));
MOCK_METHOD(void, OnObjectFragment,
(const FullTrackName& full_track_name, Location sequence,
MoqtPriority publisher_priority, MoqtObjectStatus status,
absl::string_view object, bool end_of_message),
(override));
MOCK_METHOD(void, OnSubscribeDone, (FullTrackName full_track_name),
(override));
};
class MockPublishingMonitorInterface : public MoqtPublishingMonitorInterface {
public:
MOCK_METHOD(void, OnObjectAckSupportKnown, (bool supported), (override));
MOCK_METHOD(void, OnObjectAckReceived,
(uint64_t group_id, uint64_t object_id,
quic::QuicTimeDelta delta_from_deadline),
(override));
};
class MockFetchTask : public MoqtFetchTask {
public:
MockFetchTask() {}; // No synchronous callbacks.
MockFetchTask(std::optional<MoqtFetchOk> fetch_ok,
std::optional<MoqtFetchError> fetch_error,
bool synchronous_object_available)
: synchronous_fetch_ok_(fetch_ok),
synchronous_fetch_error_(fetch_error),
synchronous_object_available_(synchronous_object_available) {
QUICHE_DCHECK(!synchronous_fetch_ok_.has_value() ||
!synchronous_fetch_error_.has_value());
}
MOCK_METHOD(MoqtFetchTask::GetNextObjectResult, GetNextObject,
(PublishedObject & output), (override));
MOCK_METHOD(absl::Status, GetStatus, (), (override));
void SetObjectAvailableCallback(ObjectsAvailableCallback callback) override {
objects_available_callback_ = std::move(callback);
if (synchronous_object_available_) {
// The first call is installed by the session to trigger stream creation.
// An object might not exist yet.
objects_available_callback_();
}
// The second call is a result of the stream replacing the callback, which
// means there is an object available.
synchronous_object_available_ = true;
}
void SetFetchResponseCallback(FetchResponseCallback callback) override {
if (synchronous_fetch_ok_.has_value()) {
std::move(callback)(*synchronous_fetch_ok_);
return;
}
if (synchronous_fetch_error_.has_value()) {
std::move(callback)(*synchronous_fetch_error_);
return;
}
fetch_response_callback_ = std::move(callback);
}
void CallObjectsAvailableCallback() { objects_available_callback_(); };
void CallFetchResponseCallback(
std::variant<MoqtFetchOk, MoqtFetchError> response) {
std::move(fetch_response_callback_)(response);
}
private:
FetchResponseCallback fetch_response_callback_;
ObjectsAvailableCallback objects_available_callback_;
std::optional<MoqtFetchOk> synchronous_fetch_ok_;
std::optional<MoqtFetchError> synchronous_fetch_error_;
bool synchronous_object_available_ = false;
};
} // namespace moqt::test
#endif // QUICHE_QUIC_MOQT_TOOLS_MOQT_MOCK_VISITOR_H_