#include "mojo/public/cpp/platform/platform_handle.h"
#include <tuple>
#include "base/check.h"
#include "base/containers/span.h"
#include "base/files/file.h"
#include "base/files/platform_file.h"
#include "base/files/scoped_temp_dir.h"
#include "base/memory/unsafe_shared_memory_region.h"
#include "base/notreached.h"
#include "base/rand_util.h"
#include "base/synchronization/waitable_event.h"
#include "base/unguessable_token.h"
#include "build/build_config.h"
#include "mojo/public/c/system/platform_handle.h"
#include "mojo/public/cpp/system/platform_handle.h"
#include "testing/gtest/include/gtest/gtest.h"
#if BUILDFLAG(IS_MAC)
#include <mach/mach_vm.h>
#endif
#if BUILDFLAG(IS_WIN)
#include "base/win/scoped_handle.h"
#else
#include "base/files/scoped_file.h"
#endif
#if BUILDFLAG(IS_ANDROID)
#include "base/android/binder.h"
#endif
namespace mojo {
namespace {
enum class HandleType { … };
enum class TestType { … };
const std::string kTestData = …;
class PlatformHandleTest : public testing::Test,
public testing::WithParamInterface<HandleType> { … };
TEST_P(PlatformHandleTest, BasicConstruction) { … }
TEST_P(PlatformHandleTest, Move) { … }
TEST_P(PlatformHandleTest, Reset) { … }
TEST_P(PlatformHandleTest, Clone) { … }
TEST_P(PlatformHandleTest, CStructConversion) { … }
#if BUILDFLAG(IS_ANDROID)
DEFINE_BINDER_CLASS(IncrementerInterface);
class Incrementer : public base::android::SupportsBinder<IncrementerInterface> {
public:
using Proxy = IncrementerInterface::BinderRef;
Incrementer() = default;
static constexpr transaction_code_t kDoIncrement = 42;
static int32_t DoIncrement(Proxy& proxy, int32_t value) {
const auto reply = *proxy.Transact(
kDoIncrement,
[value](const auto& parcel) { return parcel.WriteInt32(value); });
return *reply.reader().ReadInt32();
}
void WaitForDisconnect() { disconnect_.Wait(); }
private:
~Incrementer() override = default;
base::android::BinderStatusOr<void> OnBinderTransaction(
transaction_code_t code,
const base::android::ParcelReader& in,
const base::android::ParcelWriter& out) override {
EXPECT_EQ(kDoIncrement, code);
return out.WriteInt32(*in.ReadInt32() + 1);
}
void OnBinderDestroyed() override { disconnect_.Signal(); }
base::WaitableEvent disconnect_;
};
TEST(PlatformHandleBinderTest, HandleTypeAndValidity) {
if (!base::android::IsNativeBinderAvailable()) {
GTEST_SKIP() << "This test is only valid with native Binder support (Q+)";
}
auto handle = PlatformHandle(base::android::BinderRef());
EXPECT_TRUE(handle.is_binder());
EXPECT_FALSE(handle.is_valid_binder());
EXPECT_FALSE(handle.is_fd());
EXPECT_FALSE(handle.is_valid_fd());
EXPECT_FALSE(handle.is_valid());
auto incrementer = base::MakeRefCounted<Incrementer>();
handle = PlatformHandle(incrementer->GetBinder());
EXPECT_TRUE(handle.is_binder());
EXPECT_TRUE(handle.is_valid_binder());
EXPECT_FALSE(handle.is_fd());
EXPECT_FALSE(handle.is_valid_fd());
EXPECT_TRUE(handle.is_valid());
auto proxy = Incrementer::Proxy(handle.GetBinder());
EXPECT_EQ(3, Incrementer::DoIncrement(proxy, 2));
PlatformHandle other = std::move(handle);
EXPECT_FALSE(handle.is_binder());
EXPECT_FALSE(handle.is_valid_binder());
EXPECT_FALSE(handle.is_valid());
EXPECT_FALSE(handle.GetBinder());
EXPECT_FALSE(handle.TakeBinder());
EXPECT_TRUE(other.is_binder());
EXPECT_TRUE(other.is_valid_binder());
EXPECT_TRUE(other.is_valid());
EXPECT_TRUE(other.GetBinder());
auto binder = other.TakeBinder();
EXPECT_TRUE(binder);
EXPECT_FALSE(other.is_binder());
EXPECT_FALSE(other.is_valid());
proxy = Incrementer::Proxy(binder);
EXPECT_EQ(7, Incrementer::DoIncrement(proxy, 6));
proxy.reset();
binder.reset();
incrementer->WaitForDisconnect();
}
TEST(PlatformHandleBinderTest, WrapUnwrap) {
if (!base::android::IsNativeBinderAvailable()) {
GTEST_SKIP() << "This test is only valid with native Binder support (Q+)";
}
Incrementer::Proxy proxy;
auto handle = WrapPlatformHandle(PlatformHandle(std::move(proxy)));
EXPECT_FALSE(handle.is_valid());
auto incrementer = base::MakeRefCounted<Incrementer>();
proxy = Incrementer::Proxy(incrementer->GetBinder());
EXPECT_EQ(43, Incrementer::DoIncrement(proxy, 42));
handle = WrapPlatformHandle(PlatformHandle(std::move(proxy)));
EXPECT_TRUE(handle.is_valid());
proxy =
Incrementer::Proxy(UnwrapPlatformHandle(std::move(handle)).TakeBinder());
EXPECT_EQ(9001, Incrementer::DoIncrement(proxy, 9000));
}
#endif
INSTANTIATE_TEST_SUITE_P(…);
}
}