blob: b75a0c5e88dea696625c419079f60b80bfb42953 [file] [log] [blame]
// Copyright 2024 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_TEST_TOOLS_MOQT_FRAMER_UTILS_H_
#define QUICHE_QUIC_MOQT_TEST_TOOLS_MOQT_FRAMER_UTILS_H_
#include <cstdint>
#include <optional>
#include <string>
#include <variant>
#include <vector>
#include "absl/status/status.h"
#include "absl/strings/str_join.h"
#include "absl/strings/string_view.h"
#include "absl/types/span.h"
#include "quiche/quic/moqt/moqt_messages.h"
#include "quiche/common/platform/api/quiche_test.h"
#include "quiche/common/quiche_data_reader.h"
#include "quiche/common/quiche_mem_slice.h"
#include "quiche/common/quiche_stream.h"
namespace moqt::test {
// TODO: remove MoqtObject from TestMessageBase::MessageStructuredData and merge
// those two types.
using MoqtGenericFrame = std::variant<
MoqtClientSetup, MoqtServerSetup, MoqtSubscribe, MoqtSubscribeOk,
MoqtSubscribeError, MoqtUnsubscribe, MoqtSubscribeDone, MoqtSubscribeUpdate,
MoqtAnnounce, MoqtAnnounceOk, MoqtAnnounceError, MoqtUnannounce,
MoqtAnnounceCancel, MoqtTrackStatus, MoqtTrackStatusOk,
MoqtTrackStatusError, MoqtGoAway, MoqtSubscribeNamespace,
MoqtSubscribeNamespaceOk, MoqtSubscribeNamespaceError,
MoqtUnsubscribeNamespace, MoqtMaxRequestId, MoqtFetch, MoqtFetchCancel,
MoqtFetchOk, MoqtFetchError, MoqtRequestsBlocked, MoqtPublish,
MoqtPublishOk, MoqtPublishError, MoqtObjectAck>;
std::string SerializeGenericMessage(const MoqtGenericFrame& frame,
bool use_webtrans = false);
// Parses a concatenation of one or more MoQT control messages.
std::vector<MoqtGenericFrame> ParseGenericMessage(absl::string_view body);
MATCHER_P(SerializedControlMessage, message,
"Matches against a specific expected MoQT message") {
std::vector<absl::string_view> data_written;
data_written.reserve(arg.size());
for (const quiche::QuicheMemSlice& slice : arg) {
data_written.push_back(slice.AsStringView());
}
std::string merged_message = absl::StrJoin(data_written, "");
return merged_message == SerializeGenericMessage(message);
}
MATCHER_P(ControlMessageOfType, expected_type,
"Matches against an MoQT message of a specific type") {
std::vector<absl::string_view> data_written;
data_written.reserve(arg.size());
for (const quiche::QuicheMemSlice& slice : arg) {
data_written.push_back(slice.AsStringView());
}
std::string merged_message = absl::StrJoin(data_written, "");
quiche::QuicheDataReader reader(merged_message);
uint64_t type_raw;
if (!reader.ReadVarInt62(&type_raw)) {
*result_listener << "Failed to extract type from the message";
return false;
}
MoqtMessageType type = static_cast<MoqtMessageType>(type_raw);
if (type != expected_type) {
*result_listener << "Expected message of type "
<< MoqtMessageTypeToString(expected_type) << ", got "
<< MoqtMessageTypeToString(type);
return false;
}
return true;
}
// gmock action for extracting an SUBSCRIBE message written onto a stream.
class StoreSubscribe {
public:
explicit StoreSubscribe(std::optional<MoqtSubscribe>* subscribe)
: subscribe_(subscribe) {}
// quiche::WriteStream::Writev() implementation.
absl::Status operator()(absl::Span<const absl::string_view> data,
const quiche::StreamWriteOptions& options) const;
private:
std::optional<MoqtSubscribe>* subscribe_;
};
} // namespace moqt::test
#endif // QUICHE_QUIC_MOQT_TEST_TOOLS_MOQT_FRAMER_UTILS_H_