Source code

Revision control

Copy as Markdown

Other Tools

/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
/*
* Test that IPC channel transaction cancellation (which applies to nested sync
* messages) works as expected.
*/
#include "gtest/gtest.h"
#include "mozilla/_ipdltest/IPDLUnitTest.h"
#include "mozilla/_ipdltest/PTestCancelChild.h"
#include "mozilla/_ipdltest/PTestCancelParent.h"
using namespace mozilla::ipc;
namespace mozilla::_ipdltest {
class TestCancelParent : public PTestCancelParent {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestCancelParent, override)
private:
IPCResult RecvCallNestedCancel() final override {
EXPECT_FALSE(SendNestedCancel()) << "SendNestedCancel should fail";
EXPECT_EQ(GetIPCChannel()->LastSendError(),
SyncSendError::CancelledAfterSend)
<< "SendNestedCancel should be cancelled";
return IPC_OK();
}
IPCResult RecvNestedCancelParent() final override {
GetIPCChannel()->CancelCurrentTransaction();
return IPC_OK();
}
IPCResult RecvCheckParent(uint32_t* reply) final override {
*reply = 42;
return IPC_OK();
}
~TestCancelParent() = default;
};
class TestCancelChild : public PTestCancelChild {
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestCancelChild, override)
private:
IPCResult RecvImmediateCancel() final override {
GetIPCChannel()->CancelCurrentTransaction();
uint32_t value = 0;
EXPECT_FALSE(SendCheckParent(&value)) << "channel should be closing";
return IPC_OK();
}
IPCResult RecvStartNestedCancel() final override {
EXPECT_FALSE(SendCallNestedCancel());
Close();
return IPC_OK();
}
IPCResult RecvNestedCancel() final override {
GetIPCChannel()->CancelCurrentTransaction();
uint32_t value = 0;
EXPECT_TRUE(SendCheckParent(&value)) << "channel should be closing";
return IPC_OK();
}
IPCResult RecvStartNestedCancelParent() final override {
EXPECT_FALSE(SendNestedCancelParent())
<< "SendNestedCancelParent should fail";
EXPECT_EQ(GetIPCChannel()->LastSendError(),
SyncSendError::CancelledAfterSend)
<< "SendNestedCancelParent should be cancelled";
uint32_t value = 0;
EXPECT_FALSE(SendCheckParent(&value));
return IPC_OK();
}
IPCResult RecvCheckChild(uint32_t* reply) final override {
*reply = 42;
return IPC_OK();
}
~TestCancelChild() = default;
};
// Nested sync messages can only be received on the main thread, so threaded
// tests can't be run (the child actor won't be on the main thread).
IPDL_TEST_ON(CROSSPROCESS, TestCancel, ImmediateCancel) {
EXPECT_FALSE(mActor->SendImmediateCancel()) << "should immediately cancel";
EXPECT_EQ(mActor->GetIPCChannel()->LastSendError(),
SyncSendError::CancelledAfterSend);
uint32_t value = 0;
EXPECT_TRUE(mActor->SendCheckChild(&value));
EXPECT_EQ(value, (uint32_t)42);
mActor->Close();
}
IPDL_TEST_ON(CROSSPROCESS, TestCancel, NestedCancel) {
EXPECT_TRUE(mActor->SendStartNestedCancel());
}
IPDL_TEST_ON(CROSSPROCESS, TestCancel, NestedCancelParent) {
EXPECT_FALSE(mActor->SendStartNestedCancelParent())
<< "StartNestedCancelParent should be cancelled";
uint32_t value = 0;
EXPECT_TRUE(mActor->SendCheckChild(&value));
EXPECT_EQ(value, (uint32_t)42);
mActor->Close();
}
} // namespace mozilla::_ipdltest