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
|