blob: 2ecdba997aa35a43dbeb969f6bd741b915023e4c [file] [log] [blame]
// Copyright 2020 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.
#include "chrome/browser/nearby_sharing/instantmessaging/stream_parser.h"
#include <string>
#include <vector>
#include "base/bind.h"
#include "chrome/browser/nearby_sharing/instantmessaging/proto/instantmessaging.pb.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace {
chrome_browser_nearby_sharing_instantmessaging::ReceiveMessagesResponse
CreateReceiveMessagesResponse(const std::string& msg) {
chrome_browser_nearby_sharing_instantmessaging::ReceiveMessagesResponse
response;
response.mutable_inbox_message()->set_message(msg);
return response;
}
chrome_browser_nearby_sharing_instantmessaging::ReceiveMessagesResponse
CreateFastPathReadyResponse() {
chrome_browser_nearby_sharing_instantmessaging::ReceiveMessagesResponse
response;
response.mutable_fast_path_ready();
return response;
}
chrome_browser_nearby_sharing_instantmessaging::StreamBody BuildProto(
const std::vector<std::string>& messages,
bool include_fast_path = false) {
chrome_browser_nearby_sharing_instantmessaging::StreamBody stream_body;
if (include_fast_path) {
stream_body.add_messages(CreateFastPathReadyResponse().SerializeAsString());
}
for (const auto& msg : messages) {
stream_body.add_messages(
CreateReceiveMessagesResponse(msg).SerializeAsString());
}
return stream_body;
}
} // namespace
class StreamParserTest : public testing::Test {
public:
StreamParserTest()
: stream_parser_(base::BindRepeating(&StreamParserTest::OnMessageReceived,
base::Unretained(this)),
base::BindRepeating(&StreamParserTest::OnFastPathReady,
base::Unretained(this))) {}
~StreamParserTest() override = default;
StreamParser& GetStreamParser() { return stream_parser_; }
int MessagesReceived() { return messages_received_.size(); }
const std::vector<std::string> GetMessages() { return messages_received_; }
bool fast_path_ready() { return fast_path_ready_; }
private:
void OnMessageReceived(const std::string& message) {
messages_received_.push_back(message);
}
void OnFastPathReady() { fast_path_ready_ = true; }
bool fast_path_ready_ = false;
StreamParser stream_parser_;
std::vector<std::string> messages_received_;
};
// The entire message is sent in one response body.
TEST_F(StreamParserTest, SingleEntireMessageAtOnce) {
std::vector<std::string> messages = {"random 42"};
chrome_browser_nearby_sharing_instantmessaging::StreamBody stream_body =
BuildProto(messages);
GetStreamParser().Append(stream_body.SerializeAsString());
EXPECT_EQ(1, MessagesReceived());
EXPECT_EQ(messages, GetMessages());
}
// More than one message is sent in one response body.
TEST_F(StreamParserTest, MultipleEntireMessagesAtOnce) {
std::vector<std::string> messages = {"random 42", "more random 98",
"helloworld 25"};
chrome_browser_nearby_sharing_instantmessaging::StreamBody stream_body =
BuildProto(messages);
GetStreamParser().Append(stream_body.SerializeAsString());
EXPECT_EQ(3, MessagesReceived());
EXPECT_EQ(messages, GetMessages());
}
// A single message is sent over multiple response bodies.
TEST_F(StreamParserTest, SingleMessageSplit) {
std::vector<std::string> messages = {"random 42 and random 92"};
chrome_browser_nearby_sharing_instantmessaging::StreamBody stream_body =
BuildProto(messages);
std::string serialized_msg = stream_body.SerializeAsString();
// Randomly chosen.
int pos = 13;
GetStreamParser().Append(serialized_msg.substr(0, pos));
EXPECT_EQ(0, MessagesReceived());
EXPECT_EQ(std::vector<std::string>(), GetMessages());
GetStreamParser().Append(serialized_msg.substr(pos));
EXPECT_EQ(1, MessagesReceived());
EXPECT_EQ(messages, GetMessages());
}
// Multiple messages are sent over multiple response bodies.
TEST_F(StreamParserTest, MultipleMessagesSplit) {
std::vector<std::string> messages_1 = {"The quick", "brown fox", "jumps"};
std::vector<std::string> messages_2 = {"over the lazy", "dog."};
std::string serialized_msg_1 = BuildProto(messages_1).SerializeAsString();
std::string serialized_msg_2 = BuildProto(messages_2).SerializeAsString();
// Randomly chosen.
int pos = 7;
std::string first_message =
serialized_msg_1 + serialized_msg_2.substr(0, pos);
std::string second_message = serialized_msg_2.substr(pos);
GetStreamParser().Append(first_message);
EXPECT_EQ(3, MessagesReceived());
EXPECT_EQ(messages_1, GetMessages());
messages_1.insert(messages_1.end(), messages_2.begin(), messages_2.end());
GetStreamParser().Append(second_message);
EXPECT_EQ(5, MessagesReceived());
EXPECT_EQ(messages_1, GetMessages());
}
// The fast path message triggers callback.
TEST_F(StreamParserTest, FastPathReadyTriggersCallback) {
std::vector<std::string> messages = {"random 42"};
chrome_browser_nearby_sharing_instantmessaging::StreamBody stream_body =
BuildProto(messages, true);
GetStreamParser().Append(stream_body.SerializeAsString());
EXPECT_TRUE(fast_path_ready());
EXPECT_EQ(1, MessagesReceived());
EXPECT_EQ(messages, GetMessages());
}