1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
|
/* -*- 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
|