#ifdef UNSAFE_BUFFERS_BUILD
#pragma allow_unsafe_buffers
#endif
#include "mojo/core/channel.h"
#include <atomic>
#include <optional>
#include "base/functional/bind.h"
#include "base/memory/page_size.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_pump_type.h"
#include "base/process/process_handle.h"
#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
#include "base/task/single_thread_task_runner.h"
#include "base/test/bind.h"
#include "base/test/task_environment.h"
#include "base/threading/thread.h"
#include "build/build_config.h"
#include "mojo/core/embedder/features.h"
#include "mojo/core/platform_handle_utils.h"
#include "mojo/public/cpp/platform/platform_channel.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo::core {
class TestChannel : public Channel { … };
class MockChannelDelegate : public Channel::Delegate { … };
Channel::MessagePtr CreateDefaultMessage(bool legacy_message) { … }
void TestMemoryEqual(const void* data1,
size_t data1_size,
const void* data2,
size_t data2_size) { … }
void TestMessagesAreEqual(Channel::Message* message1,
Channel::Message* message2,
bool legacy_messages) { … }
TEST(ChannelTest, LegacyMessageDeserialization) { … }
TEST(ChannelTest, NonLegacyMessageDeserialization) { … }
TEST(ChannelTest, OnReadLegacyMessage) { … }
TEST(ChannelTest, OnReadNonLegacyMessage) { … }
class ChannelTestShutdownAndWriteDelegate : public Channel::Delegate { … };
TEST(ChannelTest, PeerShutdownDuringRead) { … }
class RejectHandlesDelegate : public Channel::Delegate { … };
TEST(ChannelTest, RejectHandles) { … }
TEST(ChannelTest, DeserializeMessage_BadExtraHeaderSize) { … }
#if !BUILDFLAG(IS_WIN) && !BUILDFLAG(IS_APPLE) && !BUILDFLAG(IS_FUCHSIA)
TEST(ChannelTest, DeserializeMessage_NonZeroExtraHeaderSize) { … }
#endif
class CountingChannelDelegate : public Channel::Delegate { … };
TEST(ChannelTest, PeerStressTest) { … }
class CallbackChannelDelegate : public Channel::Delegate { … };
TEST(ChannelTest, MessageSizeTest) { … }
#if BUILDFLAG(IS_MAC)
TEST(ChannelTest, SendToDeadMachPortName) {
base::test::SingleThreadTaskEnvironment task_environment(
base::test::TaskEnvironment::MainThreadType::IO);
base::Thread::Options thread_options;
thread_options.message_pump_type = base::MessagePumpType::IO;
base::Thread peer_thread("channel_b_io");
peer_thread.StartWithOptions(std::move(thread_options));
PlatformChannel platform_channel;
mach_port_urefs_t send = 0, dead = 0;
mach_port_t send_name = platform_channel.local_endpoint()
.platform_handle()
.GetMachSendRight()
.get();
auto get_send_name_refs = [&send, &dead, send_name]() {
kern_return_t kr = mach_port_get_refs(mach_task_self(), send_name,
MACH_PORT_RIGHT_SEND, &send);
ASSERT_EQ(kr, KERN_SUCCESS);
kr = mach_port_get_refs(mach_task_self(), send_name,
MACH_PORT_RIGHT_DEAD_NAME, &dead);
ASSERT_EQ(kr, KERN_SUCCESS);
};
get_send_name_refs();
EXPECT_EQ(1u, send);
EXPECT_EQ(0u, dead);
ASSERT_EQ(KERN_SUCCESS, mach_port_mod_refs(mach_task_self(), send_name,
MACH_PORT_RIGHT_SEND, 1));
get_send_name_refs();
EXPECT_EQ(2u, send);
EXPECT_EQ(0u, dead);
base::apple::ScopedMachSendRight extra_send(send_name);
CallbackChannelDelegate delegate_a;
scoped_refptr<Channel> channel_a = Channel::Create(
&delegate_a, ConnectionParams(platform_channel.TakeLocalEndpoint()),
Channel::HandlePolicy::kAcceptHandles,
base::SingleThreadTaskRunner::GetCurrentDefault());
channel_a->Start();
MockChannelDelegate delegate_b;
scoped_refptr<Channel> channel_b = Channel::Create(
&delegate_b, ConnectionParams(platform_channel.TakeRemoteEndpoint()),
Channel::HandlePolicy::kAcceptHandles, peer_thread.task_runner());
channel_b->Start();
channel_b->Write(Channel::Message::CreateMessage(0, 0));
{
base::RunLoop loop;
delegate_a.set_on_message(loop.QuitClosure());
loop.Run();
}
channel_b->Write(Channel::Message::CreateMessage(0, 0));
channel_b->Write(Channel::Message::CreateMessage(0, 0));
channel_b->ShutDown();
channel_b = nullptr;
base::WaitableEvent event;
peer_thread.task_runner()->PostTask(
FROM_HERE,
base::BindOnce(&base::WaitableEvent::Signal, base::Unretained(&event)));
event.Wait();
channel_a->Write(Channel::Message::CreateMessage(0, 0));
{
base::RunLoop loop;
delegate_a.set_on_error(base::BindOnce(
[](scoped_refptr<Channel> channel, base::RunLoop* loop) {
channel->ShutDown();
channel = nullptr;
loop->QuitWhenIdle();
},
channel_a, base::Unretained(&loop)));
loop.Run();
}
get_send_name_refs();
EXPECT_EQ(0u, send);
EXPECT_EQ(1u, dead);
}
#endif
TEST(ChannelTest, ShutDownStress) { … }
class CallbackIpczChannelDelegate : public Channel::Delegate { … };
TEST(ChannelTest, IpczHeaderCompatibilityTest) { … }
}