Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1137)

Side by Side Diff: util/mach/composite_mach_message_server_test.cc

Issue 781823002: Add CompositeMachMessageServer and its test (Closed) Base URL: https://chromium.googlesource.com/crashpad/crashpad@master
Patch Set: Created 6 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « util/mach/composite_mach_message_server.cc ('k') | util/mach/exc_server_variants.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright 2014 The Crashpad Authors. All rights reserved.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "util/mach/composite_mach_message_server.h"
16
17 #include "base/strings/stringprintf.h"
18 #include "gtest/gtest.h"
19 #include "util/mach/mach_message.h"
20
21 namespace crashpad {
22 namespace test {
23 namespace {
24
25 TEST(CompositeMachMessageServer, Empty) {
26 CompositeMachMessageServer server;
27
28 EXPECT_TRUE(server.MachMessageServerRequestIDs().empty());
29
30 mach_msg_empty_rcv_t request = {};
31 EXPECT_EQ(sizeof(request.header), server.MachMessageServerRequestSize());
32
33 mig_reply_error_t reply = {};
34 EXPECT_EQ(sizeof(reply), server.MachMessageServerReplySize());
35
36 bool destroy_complex_request = false;
37 EXPECT_FALSE(server.MachMessageServerFunction(
38 &request.header, &reply.Head, &destroy_complex_request));
39 EXPECT_EQ(MIG_BAD_ID, reply.RetCode);
40 }
41
42 class TestMachMessageHandler : public MachMessageServer::Interface {
43 public:
44 TestMachMessageHandler()
45 : MachMessageServer::Interface(),
46 request_ids_(),
47 request_size_(0),
48 reply_size_(0),
49 return_code_(KERN_FAILURE),
50 return_value_(false),
51 destroy_complex_request_(false) {
52 }
53
54 ~TestMachMessageHandler() {
55 }
56
57 void SetReturnCodes(bool return_value,
58 kern_return_t return_code,
59 bool destroy_complex_request) {
60 return_value_ = return_value;
61 return_code_ = return_code;
62 destroy_complex_request_ = destroy_complex_request;
63 }
64
65 void AddRequestID(mach_msg_id_t request_id) {
66 request_ids_.insert(request_id);
67 }
68
69 void SetRequestSize(mach_msg_size_t request_size) {
70 request_size_ = request_size;
71 }
72
73 void SetReplySize(mach_msg_size_t reply_size) {
74 reply_size_ = reply_size;
75 }
76
77 // MachMessageServer::Interface:
78
79 bool MachMessageServerFunction(const mach_msg_header_t* in,
80 mach_msg_header_t* out,
81 bool* destroy_complex_request) override {
82 EXPECT_NE(request_ids_.end(), request_ids_.find(in->msgh_id));
83
84 *destroy_complex_request = destroy_complex_request_;
85 PrepareMIGReplyFromRequest(in, out);
86 SetMIGReplyError(out, return_code_);
87 return return_value_;
88 }
89
90 std::set<mach_msg_id_t> MachMessageServerRequestIDs() override {
91 return request_ids_;
92 }
93
94 mach_msg_size_t MachMessageServerRequestSize() override {
95 return request_size_;
96 }
97
98 mach_msg_size_t MachMessageServerReplySize() override {
99 return reply_size_;
100 }
101
102 private:
103 std::set<mach_msg_id_t> request_ids_;
104 mach_msg_size_t request_size_;
105 mach_msg_size_t reply_size_;
106 kern_return_t return_code_;
107 bool return_value_;
108 bool destroy_complex_request_;
109
110 DISALLOW_COPY_AND_ASSIGN(TestMachMessageHandler);
111 };
112
113 TEST(CompositeMachMessageServer, HandlerDoesNotHandle) {
114 TestMachMessageHandler handler;
115
116 CompositeMachMessageServer server;
117 server.AddHandler(&handler);
118
119 EXPECT_TRUE(server.MachMessageServerRequestIDs().empty());
120
121 mach_msg_empty_rcv_t request = {};
122 EXPECT_EQ(sizeof(request.header), server.MachMessageServerRequestSize());
123
124 mig_reply_error_t reply = {};
125 EXPECT_EQ(sizeof(reply), server.MachMessageServerReplySize());
126
127 bool destroy_complex_request = false;
128 EXPECT_FALSE(server.MachMessageServerFunction(
129 &request.header, &reply.Head, &destroy_complex_request));
130 EXPECT_EQ(MIG_BAD_ID, reply.RetCode);
131 EXPECT_FALSE(destroy_complex_request);
132 }
133
134 TEST(CompositeMachMessageServer, OneHandler) {
135 const mach_msg_id_t kRequestID = 100;
136 const mach_msg_size_t kRequestSize = 256;
137 const mach_msg_size_t kReplySize = 128;
138 const kern_return_t kReturnCode = KERN_SUCCESS;
139
140 TestMachMessageHandler handler;
141 handler.AddRequestID(kRequestID);
142 handler.SetRequestSize(kRequestSize);
143 handler.SetReplySize(kReplySize);
144 handler.SetReturnCodes(true, kReturnCode, true);
145
146 CompositeMachMessageServer server;
147
148 // The chosen request and reply sizes must be larger than the defaults for
149 // that portion fo the test to be valid.
150 EXPECT_GT(kRequestSize, server.MachMessageServerRequestSize());
151 EXPECT_GT(kReplySize, server.MachMessageServerReplySize());
152
153 server.AddHandler(&handler);
154
155 std::set<mach_msg_id_t> expect_request_ids;
156 expect_request_ids.insert(kRequestID);
157 EXPECT_EQ(expect_request_ids, server.MachMessageServerRequestIDs());
158
159 EXPECT_EQ(kRequestSize, server.MachMessageServerRequestSize());
160 EXPECT_EQ(kReplySize, server.MachMessageServerReplySize());
161
162 mach_msg_empty_rcv_t request = {};
163 mig_reply_error_t reply = {};
164
165 // Send a message with an unknown request ID.
166 request.header.msgh_id = 0;
167 bool destroy_complex_request = false;
168 EXPECT_FALSE(server.MachMessageServerFunction(
169 &request.header, &reply.Head, &destroy_complex_request));
170 EXPECT_EQ(MIG_BAD_ID, reply.RetCode);
171 EXPECT_FALSE(destroy_complex_request);
172
173 // Send a message with a known request ID.
174 request.header.msgh_id = kRequestID;
175 EXPECT_TRUE(server.MachMessageServerFunction(
176 &request.header, &reply.Head, &destroy_complex_request));
177 EXPECT_EQ(kReturnCode, reply.RetCode);
178 EXPECT_TRUE(destroy_complex_request);
179 }
180
181 TEST(CompositeMachMessageServer, ThreeHandlers) {
182 const mach_msg_id_t kRequestIDs0[] = {5};
183 const kern_return_t kReturnCode0 = KERN_SUCCESS;
184
185 const mach_msg_id_t kRequestIDs1[] = {4, 7};
186 const kern_return_t kReturnCode1 = KERN_PROTECTION_FAILURE;
187
188 const mach_msg_id_t kRequestIDs2[] = {10, 0, 20};
189 const mach_msg_size_t kRequestSize2 = 6144;
190 const mach_msg_size_t kReplySize2 = 16384;
191 const kern_return_t kReturnCode2 = KERN_NOT_RECEIVER;
192
193 TestMachMessageHandler handlers[3];
194 std::set<mach_msg_id_t> expect_request_ids;
195
196 for (size_t index = 0; index < arraysize(kRequestIDs0); ++index) {
197 const mach_msg_id_t request_id = kRequestIDs0[index];
198 handlers[0].AddRequestID(request_id);
199 expect_request_ids.insert(request_id);
200 }
201 handlers[0].SetRequestSize(sizeof(mach_msg_header_t));
202 handlers[0].SetReplySize(sizeof(mig_reply_error_t));
203 handlers[0].SetReturnCodes(true, kReturnCode0, false);
204
205 for (size_t index = 0; index < arraysize(kRequestIDs1); ++index) {
206 const mach_msg_id_t request_id = kRequestIDs1[index];
207 handlers[1].AddRequestID(request_id);
208 expect_request_ids.insert(request_id);
209 }
210 handlers[1].SetRequestSize(100);
211 handlers[1].SetReplySize(200);
212 handlers[1].SetReturnCodes(false, kReturnCode1, true);
213
214 for (size_t index = 0; index < arraysize(kRequestIDs2); ++index) {
215 const mach_msg_id_t request_id = kRequestIDs2[index];
216 handlers[2].AddRequestID(request_id);
217 expect_request_ids.insert(request_id);
218 }
219 handlers[2].SetRequestSize(kRequestSize2);
220 handlers[2].SetReplySize(kReplySize2);
221 handlers[2].SetReturnCodes(true, kReturnCode2, true);
222
223 CompositeMachMessageServer server;
224
225 // The chosen request and reply sizes must be larger than the defaults for
226 // that portion fo the test to be valid.
227 EXPECT_GT(kRequestSize2, server.MachMessageServerRequestSize());
228 EXPECT_GT(kReplySize2, server.MachMessageServerReplySize());
229
230 server.AddHandler(&handlers[0]);
231 server.AddHandler(&handlers[1]);
232 server.AddHandler(&handlers[2]);
233
234 EXPECT_EQ(expect_request_ids, server.MachMessageServerRequestIDs());
235
236 EXPECT_EQ(kRequestSize2, server.MachMessageServerRequestSize());
237 EXPECT_EQ(kReplySize2, server.MachMessageServerReplySize());
238
239 mach_msg_empty_rcv_t request = {};
240 mig_reply_error_t reply = {};
241
242 // Send a message with an unknown request ID.
243 request.header.msgh_id = 100;
244 bool destroy_complex_request = false;
245 EXPECT_FALSE(server.MachMessageServerFunction(
246 &request.header, &reply.Head, &destroy_complex_request));
247 EXPECT_EQ(MIG_BAD_ID, reply.RetCode);
248 EXPECT_FALSE(destroy_complex_request);
249
250 // Send messages with known request IDs.
251
252 for (size_t index = 0; index < arraysize(kRequestIDs0); ++index) {
253 request.header.msgh_id = kRequestIDs0[index];
254 SCOPED_TRACE(base::StringPrintf(
255 "handler 0, index %zu, id %d", index, request.header.msgh_id));
256
257 EXPECT_TRUE(server.MachMessageServerFunction(
258 &request.header, &reply.Head, &destroy_complex_request));
259 EXPECT_EQ(kReturnCode0, reply.RetCode);
260 EXPECT_FALSE(destroy_complex_request);
261 }
262
263 for (size_t index = 0; index < arraysize(kRequestIDs1); ++index) {
264 request.header.msgh_id = kRequestIDs1[index];
265 SCOPED_TRACE(base::StringPrintf(
266 "handler 1, index %zu, id %d", index, request.header.msgh_id));
267
268 EXPECT_FALSE(server.MachMessageServerFunction(
269 &request.header, &reply.Head, &destroy_complex_request));
270 EXPECT_EQ(kReturnCode1, reply.RetCode);
271 EXPECT_TRUE(destroy_complex_request);
272 }
273
274 for (size_t index = 0; index < arraysize(kRequestIDs2); ++index) {
275 request.header.msgh_id = kRequestIDs2[index];
276 SCOPED_TRACE(base::StringPrintf(
277 "handler 2, index %zu, id %d", index, request.header.msgh_id));
278
279 EXPECT_TRUE(server.MachMessageServerFunction(
280 &request.header, &reply.Head, &destroy_complex_request));
281 EXPECT_EQ(kReturnCode2, reply.RetCode);
282 EXPECT_TRUE(destroy_complex_request);
283 }
284 }
285
286 // CompositeMachMessageServer can’t deal with two handlers that want to handle
287 // the same request ID.
288 TEST(CompositeMachMessageServerDeathTest, DuplicateRequestID) {
289 const mach_msg_id_t kRequestID = 400;
290
291 TestMachMessageHandler handlers[2];
292 handlers[0].AddRequestID(kRequestID);
293 handlers[1].AddRequestID(kRequestID);
294
295 CompositeMachMessageServer server;
296
297 server.AddHandler(&handlers[0]);
298 EXPECT_DEATH(server.AddHandler(&handlers[1]), "duplicate request ID");
299 }
300
301 } // namespace
302 } // namespace test
303 } // namespace crashpad
OLDNEW
« no previous file with comments | « util/mach/composite_mach_message_server.cc ('k') | util/mach/exc_server_variants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698