OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "mojo/system/message_pipe.h" | 5 #include "mojo/system/message_pipe.h" |
6 | 6 |
7 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
8 #include "base/threading/platform_thread.h" // For |Sleep()|. | 8 #include "base/threading/platform_thread.h" // For |Sleep()|. |
9 #include "base/time/time.h" | 9 #include "base/time/time.h" |
10 #include "mojo/system/waiter.h" | 10 #include "mojo/system/waiter.h" |
(...skipping 25 matching lines...) Expand all Loading... |
36 | 36 |
37 // Nothing to read yet on port 0. | 37 // Nothing to read yet on port 0. |
38 buffer[0] = 123; | 38 buffer[0] = 123; |
39 buffer[1] = 456; | 39 buffer[1] = 456; |
40 buffer_size = kBufferSize; | 40 buffer_size = kBufferSize; |
41 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 41 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
42 mp->ReadMessage(0, | 42 mp->ReadMessage(0, |
43 UserPointer<void>(buffer), | 43 UserPointer<void>(buffer), |
44 MakeUserPointer(&buffer_size), | 44 MakeUserPointer(&buffer_size), |
45 0, | 45 0, |
46 NULL, | 46 nullptr, |
47 MOJO_READ_MESSAGE_FLAG_NONE)); | 47 MOJO_READ_MESSAGE_FLAG_NONE)); |
48 EXPECT_EQ(kBufferSize, buffer_size); | 48 EXPECT_EQ(kBufferSize, buffer_size); |
49 EXPECT_EQ(123, buffer[0]); | 49 EXPECT_EQ(123, buffer[0]); |
50 EXPECT_EQ(456, buffer[1]); | 50 EXPECT_EQ(456, buffer[1]); |
51 | 51 |
52 // Ditto for port 1. | 52 // Ditto for port 1. |
53 buffer[0] = 123; | 53 buffer[0] = 123; |
54 buffer[1] = 456; | 54 buffer[1] = 456; |
55 buffer_size = kBufferSize; | 55 buffer_size = kBufferSize; |
56 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 56 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
57 mp->ReadMessage(1, | 57 mp->ReadMessage(1, |
58 UserPointer<void>(buffer), | 58 UserPointer<void>(buffer), |
59 MakeUserPointer(&buffer_size), | 59 MakeUserPointer(&buffer_size), |
60 0, | 60 0, |
61 NULL, | 61 nullptr, |
62 MOJO_READ_MESSAGE_FLAG_NONE)); | 62 MOJO_READ_MESSAGE_FLAG_NONE)); |
63 | 63 |
64 // Write from port 1 (to port 0). | 64 // Write from port 1 (to port 0). |
65 buffer[0] = 789012345; | 65 buffer[0] = 789012345; |
66 buffer[1] = 0; | 66 buffer[1] = 0; |
67 EXPECT_EQ(MOJO_RESULT_OK, | 67 EXPECT_EQ(MOJO_RESULT_OK, |
68 mp->WriteMessage(1, | 68 mp->WriteMessage(1, |
69 UserPointer<const void>(buffer), | 69 UserPointer<const void>(buffer), |
70 static_cast<uint32_t>(sizeof(buffer[0])), | 70 static_cast<uint32_t>(sizeof(buffer[0])), |
71 NULL, | 71 nullptr, |
72 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 72 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
73 | 73 |
74 // Read from port 0. | 74 // Read from port 0. |
75 buffer[0] = 123; | 75 buffer[0] = 123; |
76 buffer[1] = 456; | 76 buffer[1] = 456; |
77 buffer_size = kBufferSize; | 77 buffer_size = kBufferSize; |
78 EXPECT_EQ(MOJO_RESULT_OK, | 78 EXPECT_EQ(MOJO_RESULT_OK, |
79 mp->ReadMessage(0, | 79 mp->ReadMessage(0, |
80 UserPointer<void>(buffer), | 80 UserPointer<void>(buffer), |
81 MakeUserPointer(&buffer_size), | 81 MakeUserPointer(&buffer_size), |
82 0, | 82 0, |
83 NULL, | 83 nullptr, |
84 MOJO_READ_MESSAGE_FLAG_NONE)); | 84 MOJO_READ_MESSAGE_FLAG_NONE)); |
85 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 85 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
86 EXPECT_EQ(789012345, buffer[0]); | 86 EXPECT_EQ(789012345, buffer[0]); |
87 EXPECT_EQ(456, buffer[1]); | 87 EXPECT_EQ(456, buffer[1]); |
88 | 88 |
89 // Read again from port 0 -- it should be empty. | 89 // Read again from port 0 -- it should be empty. |
90 buffer_size = kBufferSize; | 90 buffer_size = kBufferSize; |
91 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 91 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
92 mp->ReadMessage(0, | 92 mp->ReadMessage(0, |
93 UserPointer<void>(buffer), | 93 UserPointer<void>(buffer), |
94 MakeUserPointer(&buffer_size), | 94 MakeUserPointer(&buffer_size), |
95 0, | 95 0, |
96 NULL, | 96 nullptr, |
97 MOJO_READ_MESSAGE_FLAG_NONE)); | 97 MOJO_READ_MESSAGE_FLAG_NONE)); |
98 | 98 |
99 // Write two messages from port 0 (to port 1). | 99 // Write two messages from port 0 (to port 1). |
100 buffer[0] = 123456789; | 100 buffer[0] = 123456789; |
101 buffer[1] = 0; | 101 buffer[1] = 0; |
102 EXPECT_EQ(MOJO_RESULT_OK, | 102 EXPECT_EQ(MOJO_RESULT_OK, |
103 mp->WriteMessage(0, | 103 mp->WriteMessage(0, |
104 UserPointer<const void>(buffer), | 104 UserPointer<const void>(buffer), |
105 static_cast<uint32_t>(sizeof(buffer[0])), | 105 static_cast<uint32_t>(sizeof(buffer[0])), |
106 NULL, | 106 nullptr, |
107 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 107 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
108 buffer[0] = 234567890; | 108 buffer[0] = 234567890; |
109 buffer[1] = 0; | 109 buffer[1] = 0; |
110 EXPECT_EQ(MOJO_RESULT_OK, | 110 EXPECT_EQ(MOJO_RESULT_OK, |
111 mp->WriteMessage(0, | 111 mp->WriteMessage(0, |
112 UserPointer<const void>(buffer), | 112 UserPointer<const void>(buffer), |
113 static_cast<uint32_t>(sizeof(buffer[0])), | 113 static_cast<uint32_t>(sizeof(buffer[0])), |
114 NULL, | 114 nullptr, |
115 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 115 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
116 | 116 |
117 // Read from port 1 with buffer size 0 (should get the size of next message). | 117 // Read from port 1 with buffer size 0 (should get the size of next message). |
118 // Also test that giving a null buffer is okay when the buffer size is 0. | 118 // Also test that giving a null buffer is okay when the buffer size is 0. |
119 buffer_size = 0; | 119 buffer_size = 0; |
120 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 120 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
121 mp->ReadMessage(1, | 121 mp->ReadMessage(1, |
122 NullUserPointer(), | 122 NullUserPointer(), |
123 MakeUserPointer(&buffer_size), | 123 MakeUserPointer(&buffer_size), |
124 0, | 124 0, |
125 NULL, | 125 nullptr, |
126 MOJO_READ_MESSAGE_FLAG_NONE)); | 126 MOJO_READ_MESSAGE_FLAG_NONE)); |
127 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 127 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
128 | 128 |
129 // Read from port 1 with buffer size 1 (too small; should get the size of next | 129 // Read from port 1 with buffer size 1 (too small; should get the size of next |
130 // message). | 130 // message). |
131 buffer[0] = 123; | 131 buffer[0] = 123; |
132 buffer[1] = 456; | 132 buffer[1] = 456; |
133 buffer_size = 1; | 133 buffer_size = 1; |
134 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 134 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
135 mp->ReadMessage(1, | 135 mp->ReadMessage(1, |
136 UserPointer<void>(buffer), | 136 UserPointer<void>(buffer), |
137 MakeUserPointer(&buffer_size), | 137 MakeUserPointer(&buffer_size), |
138 0, | 138 0, |
139 NULL, | 139 nullptr, |
140 MOJO_READ_MESSAGE_FLAG_NONE)); | 140 MOJO_READ_MESSAGE_FLAG_NONE)); |
141 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 141 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
142 EXPECT_EQ(123, buffer[0]); | 142 EXPECT_EQ(123, buffer[0]); |
143 EXPECT_EQ(456, buffer[1]); | 143 EXPECT_EQ(456, buffer[1]); |
144 | 144 |
145 // Read from port 1. | 145 // Read from port 1. |
146 buffer[0] = 123; | 146 buffer[0] = 123; |
147 buffer[1] = 456; | 147 buffer[1] = 456; |
148 buffer_size = kBufferSize; | 148 buffer_size = kBufferSize; |
149 EXPECT_EQ(MOJO_RESULT_OK, | 149 EXPECT_EQ(MOJO_RESULT_OK, |
150 mp->ReadMessage(1, | 150 mp->ReadMessage(1, |
151 UserPointer<void>(buffer), | 151 UserPointer<void>(buffer), |
152 MakeUserPointer(&buffer_size), | 152 MakeUserPointer(&buffer_size), |
153 0, | 153 0, |
154 NULL, | 154 nullptr, |
155 MOJO_READ_MESSAGE_FLAG_NONE)); | 155 MOJO_READ_MESSAGE_FLAG_NONE)); |
156 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 156 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
157 EXPECT_EQ(123456789, buffer[0]); | 157 EXPECT_EQ(123456789, buffer[0]); |
158 EXPECT_EQ(456, buffer[1]); | 158 EXPECT_EQ(456, buffer[1]); |
159 | 159 |
160 // Read again from port 1. | 160 // Read again from port 1. |
161 buffer[0] = 123; | 161 buffer[0] = 123; |
162 buffer[1] = 456; | 162 buffer[1] = 456; |
163 buffer_size = kBufferSize; | 163 buffer_size = kBufferSize; |
164 EXPECT_EQ(MOJO_RESULT_OK, | 164 EXPECT_EQ(MOJO_RESULT_OK, |
165 mp->ReadMessage(1, | 165 mp->ReadMessage(1, |
166 UserPointer<void>(buffer), | 166 UserPointer<void>(buffer), |
167 MakeUserPointer(&buffer_size), | 167 MakeUserPointer(&buffer_size), |
168 0, | 168 0, |
169 NULL, | 169 nullptr, |
170 MOJO_READ_MESSAGE_FLAG_NONE)); | 170 MOJO_READ_MESSAGE_FLAG_NONE)); |
171 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 171 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
172 EXPECT_EQ(234567890, buffer[0]); | 172 EXPECT_EQ(234567890, buffer[0]); |
173 EXPECT_EQ(456, buffer[1]); | 173 EXPECT_EQ(456, buffer[1]); |
174 | 174 |
175 // Read again from port 1 -- it should be empty. | 175 // Read again from port 1 -- it should be empty. |
176 buffer_size = kBufferSize; | 176 buffer_size = kBufferSize; |
177 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 177 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
178 mp->ReadMessage(1, | 178 mp->ReadMessage(1, |
179 UserPointer<void>(buffer), | 179 UserPointer<void>(buffer), |
180 MakeUserPointer(&buffer_size), | 180 MakeUserPointer(&buffer_size), |
181 0, | 181 0, |
182 NULL, | 182 nullptr, |
183 MOJO_READ_MESSAGE_FLAG_NONE)); | 183 MOJO_READ_MESSAGE_FLAG_NONE)); |
184 | 184 |
185 // Write from port 0 (to port 1). | 185 // Write from port 0 (to port 1). |
186 buffer[0] = 345678901; | 186 buffer[0] = 345678901; |
187 buffer[1] = 0; | 187 buffer[1] = 0; |
188 EXPECT_EQ(MOJO_RESULT_OK, | 188 EXPECT_EQ(MOJO_RESULT_OK, |
189 mp->WriteMessage(0, | 189 mp->WriteMessage(0, |
190 UserPointer<const void>(buffer), | 190 UserPointer<const void>(buffer), |
191 static_cast<uint32_t>(sizeof(buffer[0])), | 191 static_cast<uint32_t>(sizeof(buffer[0])), |
192 NULL, | 192 nullptr, |
193 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 193 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
194 | 194 |
195 // Close port 0. | 195 // Close port 0. |
196 mp->Close(0); | 196 mp->Close(0); |
197 | 197 |
198 // Try to write from port 1 (to port 0). | 198 // Try to write from port 1 (to port 0). |
199 buffer[0] = 456789012; | 199 buffer[0] = 456789012; |
200 buffer[1] = 0; | 200 buffer[1] = 0; |
201 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 201 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
202 mp->WriteMessage(1, | 202 mp->WriteMessage(1, |
203 UserPointer<const void>(buffer), | 203 UserPointer<const void>(buffer), |
204 static_cast<uint32_t>(sizeof(buffer[0])), | 204 static_cast<uint32_t>(sizeof(buffer[0])), |
205 NULL, | 205 nullptr, |
206 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 206 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
207 | 207 |
208 // Read from port 1; should still get message (even though port 0 was closed). | 208 // Read from port 1; should still get message (even though port 0 was closed). |
209 buffer[0] = 123; | 209 buffer[0] = 123; |
210 buffer[1] = 456; | 210 buffer[1] = 456; |
211 buffer_size = kBufferSize; | 211 buffer_size = kBufferSize; |
212 EXPECT_EQ(MOJO_RESULT_OK, | 212 EXPECT_EQ(MOJO_RESULT_OK, |
213 mp->ReadMessage(1, | 213 mp->ReadMessage(1, |
214 UserPointer<void>(buffer), | 214 UserPointer<void>(buffer), |
215 MakeUserPointer(&buffer_size), | 215 MakeUserPointer(&buffer_size), |
216 0, | 216 0, |
217 NULL, | 217 nullptr, |
218 MOJO_READ_MESSAGE_FLAG_NONE)); | 218 MOJO_READ_MESSAGE_FLAG_NONE)); |
219 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 219 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
220 EXPECT_EQ(345678901, buffer[0]); | 220 EXPECT_EQ(345678901, buffer[0]); |
221 EXPECT_EQ(456, buffer[1]); | 221 EXPECT_EQ(456, buffer[1]); |
222 | 222 |
223 // Read again from port 1 -- it should be empty (and port 0 is closed). | 223 // Read again from port 1 -- it should be empty (and port 0 is closed). |
224 buffer_size = kBufferSize; | 224 buffer_size = kBufferSize; |
225 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 225 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
226 mp->ReadMessage(1, | 226 mp->ReadMessage(1, |
227 UserPointer<void>(buffer), | 227 UserPointer<void>(buffer), |
228 MakeUserPointer(&buffer_size), | 228 MakeUserPointer(&buffer_size), |
229 0, | 229 0, |
230 NULL, | 230 nullptr, |
231 MOJO_READ_MESSAGE_FLAG_NONE)); | 231 MOJO_READ_MESSAGE_FLAG_NONE)); |
232 | 232 |
233 mp->Close(1); | 233 mp->Close(1); |
234 } | 234 } |
235 | 235 |
236 TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) { | 236 TEST(MessagePipeTest, CloseWithQueuedIncomingMessages) { |
237 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 237 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); |
238 | 238 |
239 int32_t buffer[1]; | 239 int32_t buffer[1]; |
240 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 240 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
241 uint32_t buffer_size; | 241 uint32_t buffer_size; |
242 | 242 |
243 // Write some messages from port 1 (to port 0). | 243 // Write some messages from port 1 (to port 0). |
244 for (int32_t i = 0; i < 5; i++) { | 244 for (int32_t i = 0; i < 5; i++) { |
245 buffer[0] = i; | 245 buffer[0] = i; |
246 EXPECT_EQ(MOJO_RESULT_OK, | 246 EXPECT_EQ(MOJO_RESULT_OK, |
247 mp->WriteMessage(1, | 247 mp->WriteMessage(1, |
248 UserPointer<const void>(buffer), | 248 UserPointer<const void>(buffer), |
249 kBufferSize, | 249 kBufferSize, |
250 NULL, | 250 nullptr, |
251 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 251 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
252 } | 252 } |
253 | 253 |
254 // Port 0 shouldn't be empty. | 254 // Port 0 shouldn't be empty. |
255 buffer_size = 0; | 255 buffer_size = 0; |
256 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 256 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
257 mp->ReadMessage(0, | 257 mp->ReadMessage(0, |
258 NullUserPointer(), | 258 NullUserPointer(), |
259 MakeUserPointer(&buffer_size), | 259 MakeUserPointer(&buffer_size), |
260 0, | 260 0, |
261 NULL, | 261 nullptr, |
262 MOJO_READ_MESSAGE_FLAG_NONE)); | 262 MOJO_READ_MESSAGE_FLAG_NONE)); |
263 EXPECT_EQ(kBufferSize, buffer_size); | 263 EXPECT_EQ(kBufferSize, buffer_size); |
264 | 264 |
265 // Close port 0 first, which should have outstanding (incoming) messages. | 265 // Close port 0 first, which should have outstanding (incoming) messages. |
266 mp->Close(0); | 266 mp->Close(0); |
267 mp->Close(1); | 267 mp->Close(1); |
268 } | 268 } |
269 | 269 |
270 TEST(MessagePipeTest, DiscardMode) { | 270 TEST(MessagePipeTest, DiscardMode) { |
271 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 271 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); |
272 | 272 |
273 int32_t buffer[2]; | 273 int32_t buffer[2]; |
274 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 274 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
275 uint32_t buffer_size; | 275 uint32_t buffer_size; |
276 | 276 |
277 // Write from port 1 (to port 0). | 277 // Write from port 1 (to port 0). |
278 buffer[0] = 789012345; | 278 buffer[0] = 789012345; |
279 buffer[1] = 0; | 279 buffer[1] = 0; |
280 EXPECT_EQ(MOJO_RESULT_OK, | 280 EXPECT_EQ(MOJO_RESULT_OK, |
281 mp->WriteMessage(1, | 281 mp->WriteMessage(1, |
282 UserPointer<const void>(buffer), | 282 UserPointer<const void>(buffer), |
283 static_cast<uint32_t>(sizeof(buffer[0])), | 283 static_cast<uint32_t>(sizeof(buffer[0])), |
284 NULL, | 284 nullptr, |
285 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 285 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
286 | 286 |
287 // Read/discard from port 0 (no buffer); get size. | 287 // Read/discard from port 0 (no buffer); get size. |
288 buffer_size = 0; | 288 buffer_size = 0; |
289 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 289 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
290 mp->ReadMessage(0, | 290 mp->ReadMessage(0, |
291 NullUserPointer(), | 291 NullUserPointer(), |
292 MakeUserPointer(&buffer_size), | 292 MakeUserPointer(&buffer_size), |
293 0, | 293 0, |
294 NULL, | 294 nullptr, |
295 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 295 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
296 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 296 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
297 | 297 |
298 // Read again from port 0 -- it should be empty. | 298 // Read again from port 0 -- it should be empty. |
299 buffer_size = kBufferSize; | 299 buffer_size = kBufferSize; |
300 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 300 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
301 mp->ReadMessage(0, | 301 mp->ReadMessage(0, |
302 UserPointer<void>(buffer), | 302 UserPointer<void>(buffer), |
303 MakeUserPointer(&buffer_size), | 303 MakeUserPointer(&buffer_size), |
304 0, | 304 0, |
305 NULL, | 305 nullptr, |
306 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 306 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
307 | 307 |
308 // Write from port 1 (to port 0). | 308 // Write from port 1 (to port 0). |
309 buffer[0] = 890123456; | 309 buffer[0] = 890123456; |
310 buffer[1] = 0; | 310 buffer[1] = 0; |
311 EXPECT_EQ(MOJO_RESULT_OK, | 311 EXPECT_EQ(MOJO_RESULT_OK, |
312 mp->WriteMessage(1, | 312 mp->WriteMessage(1, |
313 UserPointer<const void>(buffer), | 313 UserPointer<const void>(buffer), |
314 static_cast<uint32_t>(sizeof(buffer[0])), | 314 static_cast<uint32_t>(sizeof(buffer[0])), |
315 NULL, | 315 nullptr, |
316 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 316 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
317 | 317 |
318 // Read from port 0 (buffer big enough). | 318 // Read from port 0 (buffer big enough). |
319 buffer[0] = 123; | 319 buffer[0] = 123; |
320 buffer[1] = 456; | 320 buffer[1] = 456; |
321 buffer_size = kBufferSize; | 321 buffer_size = kBufferSize; |
322 EXPECT_EQ(MOJO_RESULT_OK, | 322 EXPECT_EQ(MOJO_RESULT_OK, |
323 mp->ReadMessage(0, | 323 mp->ReadMessage(0, |
324 UserPointer<void>(buffer), | 324 UserPointer<void>(buffer), |
325 MakeUserPointer(&buffer_size), | 325 MakeUserPointer(&buffer_size), |
326 0, | 326 0, |
327 NULL, | 327 nullptr, |
328 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 328 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
329 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 329 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
330 EXPECT_EQ(890123456, buffer[0]); | 330 EXPECT_EQ(890123456, buffer[0]); |
331 EXPECT_EQ(456, buffer[1]); | 331 EXPECT_EQ(456, buffer[1]); |
332 | 332 |
333 // Read again from port 0 -- it should be empty. | 333 // Read again from port 0 -- it should be empty. |
334 buffer_size = kBufferSize; | 334 buffer_size = kBufferSize; |
335 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 335 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
336 mp->ReadMessage(0, | 336 mp->ReadMessage(0, |
337 UserPointer<void>(buffer), | 337 UserPointer<void>(buffer), |
338 MakeUserPointer(&buffer_size), | 338 MakeUserPointer(&buffer_size), |
339 0, | 339 0, |
340 NULL, | 340 nullptr, |
341 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 341 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
342 | 342 |
343 // Write from port 1 (to port 0). | 343 // Write from port 1 (to port 0). |
344 buffer[0] = 901234567; | 344 buffer[0] = 901234567; |
345 buffer[1] = 0; | 345 buffer[1] = 0; |
346 EXPECT_EQ(MOJO_RESULT_OK, | 346 EXPECT_EQ(MOJO_RESULT_OK, |
347 mp->WriteMessage(1, | 347 mp->WriteMessage(1, |
348 UserPointer<const void>(buffer), | 348 UserPointer<const void>(buffer), |
349 static_cast<uint32_t>(sizeof(buffer[0])), | 349 static_cast<uint32_t>(sizeof(buffer[0])), |
350 NULL, | 350 nullptr, |
351 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 351 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
352 | 352 |
353 // Read/discard from port 0 (buffer too small); get size. | 353 // Read/discard from port 0 (buffer too small); get size. |
354 buffer_size = 1; | 354 buffer_size = 1; |
355 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 355 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
356 mp->ReadMessage(0, | 356 mp->ReadMessage(0, |
357 UserPointer<void>(buffer), | 357 UserPointer<void>(buffer), |
358 MakeUserPointer(&buffer_size), | 358 MakeUserPointer(&buffer_size), |
359 0, | 359 0, |
360 NULL, | 360 nullptr, |
361 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 361 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
362 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); | 362 EXPECT_EQ(static_cast<uint32_t>(sizeof(buffer[0])), buffer_size); |
363 | 363 |
364 // Read again from port 0 -- it should be empty. | 364 // Read again from port 0 -- it should be empty. |
365 buffer_size = kBufferSize; | 365 buffer_size = kBufferSize; |
366 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 366 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
367 mp->ReadMessage(0, | 367 mp->ReadMessage(0, |
368 UserPointer<void>(buffer), | 368 UserPointer<void>(buffer), |
369 MakeUserPointer(&buffer_size), | 369 MakeUserPointer(&buffer_size), |
370 0, | 370 0, |
371 NULL, | 371 nullptr, |
372 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 372 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
373 | 373 |
374 // Write from port 1 (to port 0). | 374 // Write from port 1 (to port 0). |
375 buffer[0] = 123456789; | 375 buffer[0] = 123456789; |
376 buffer[1] = 0; | 376 buffer[1] = 0; |
377 EXPECT_EQ(MOJO_RESULT_OK, | 377 EXPECT_EQ(MOJO_RESULT_OK, |
378 mp->WriteMessage(1, | 378 mp->WriteMessage(1, |
379 UserPointer<const void>(buffer), | 379 UserPointer<const void>(buffer), |
380 static_cast<uint32_t>(sizeof(buffer[0])), | 380 static_cast<uint32_t>(sizeof(buffer[0])), |
381 NULL, | 381 nullptr, |
382 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 382 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
383 | 383 |
384 // Discard from port 0. | 384 // Discard from port 0. |
385 buffer_size = 1; | 385 buffer_size = 1; |
386 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, | 386 EXPECT_EQ(MOJO_RESULT_RESOURCE_EXHAUSTED, |
387 mp->ReadMessage(0, | 387 mp->ReadMessage(0, |
388 NullUserPointer(), | 388 NullUserPointer(), |
389 NullUserPointer(), | 389 NullUserPointer(), |
390 0, | 390 0, |
391 NULL, | 391 nullptr, |
392 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 392 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
393 | 393 |
394 // Read again from port 0 -- it should be empty. | 394 // Read again from port 0 -- it should be empty. |
395 buffer_size = kBufferSize; | 395 buffer_size = kBufferSize; |
396 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, | 396 EXPECT_EQ(MOJO_RESULT_SHOULD_WAIT, |
397 mp->ReadMessage(0, | 397 mp->ReadMessage(0, |
398 UserPointer<void>(buffer), | 398 UserPointer<void>(buffer), |
399 MakeUserPointer(&buffer_size), | 399 MakeUserPointer(&buffer_size), |
400 0, | 400 0, |
401 NULL, | 401 nullptr, |
402 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); | 402 MOJO_READ_MESSAGE_FLAG_MAY_DISCARD)); |
403 | 403 |
404 mp->Close(0); | 404 mp->Close(0); |
405 mp->Close(1); | 405 mp->Close(1); |
406 } | 406 } |
407 | 407 |
408 TEST(MessagePipeTest, BasicWaiting) { | 408 TEST(MessagePipeTest, BasicWaiting) { |
409 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 409 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); |
410 Waiter waiter; | 410 Waiter waiter; |
411 HandleSignalsState hss; | 411 HandleSignalsState hss; |
(...skipping 19 matching lines...) Expand all Loading... |
431 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 431 MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
432 0, | 432 0, |
433 &hss)); | 433 &hss)); |
434 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | 434 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |
435 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 435 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
436 hss.satisfiable_signals); | 436 hss.satisfiable_signals); |
437 | 437 |
438 // Not yet readable. | 438 // Not yet readable. |
439 waiter.Init(); | 439 waiter.Init(); |
440 ASSERT_EQ(MOJO_RESULT_OK, | 440 ASSERT_EQ(MOJO_RESULT_OK, |
441 mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, NULL)); | 441 mp->AddWaiter(0, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); |
442 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, NULL)); | 442 EXPECT_EQ(MOJO_RESULT_DEADLINE_EXCEEDED, waiter.Wait(0, nullptr)); |
443 hss = HandleSignalsState(); | 443 hss = HandleSignalsState(); |
444 mp->RemoveWaiter(0, &waiter, &hss); | 444 mp->RemoveWaiter(0, &waiter, &hss); |
445 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); | 445 EXPECT_EQ(MOJO_HANDLE_SIGNAL_WRITABLE, hss.satisfied_signals); |
446 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 446 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
447 hss.satisfiable_signals); | 447 hss.satisfiable_signals); |
448 | 448 |
449 // Write from port 0 (to port 1), to make port 1 readable. | 449 // Write from port 0 (to port 1), to make port 1 readable. |
450 buffer[0] = 123456789; | 450 buffer[0] = 123456789; |
451 EXPECT_EQ(MOJO_RESULT_OK, | 451 EXPECT_EQ(MOJO_RESULT_OK, |
452 mp->WriteMessage(0, | 452 mp->WriteMessage(0, |
453 UserPointer<const void>(buffer), | 453 UserPointer<const void>(buffer), |
454 kBufferSize, | 454 kBufferSize, |
455 NULL, | 455 nullptr, |
456 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 456 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
457 | 457 |
458 // Port 1 should already be readable now. | 458 // Port 1 should already be readable now. |
459 waiter.Init(); | 459 waiter.Init(); |
460 hss = HandleSignalsState(); | 460 hss = HandleSignalsState(); |
461 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, | 461 EXPECT_EQ(MOJO_RESULT_ALREADY_EXISTS, |
462 mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); | 462 mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 2, &hss)); |
463 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 463 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
464 hss.satisfied_signals); | 464 hss.satisfied_signals); |
465 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 465 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
507 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); | 507 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE, hss.satisfiable_signals); |
508 | 508 |
509 // Read from port 1. | 509 // Read from port 1. |
510 buffer[0] = 0; | 510 buffer[0] = 0; |
511 buffer_size = kBufferSize; | 511 buffer_size = kBufferSize; |
512 EXPECT_EQ(MOJO_RESULT_OK, | 512 EXPECT_EQ(MOJO_RESULT_OK, |
513 mp->ReadMessage(1, | 513 mp->ReadMessage(1, |
514 UserPointer<void>(buffer), | 514 UserPointer<void>(buffer), |
515 MakeUserPointer(&buffer_size), | 515 MakeUserPointer(&buffer_size), |
516 0, | 516 0, |
517 NULL, | 517 nullptr, |
518 MOJO_READ_MESSAGE_FLAG_NONE)); | 518 MOJO_READ_MESSAGE_FLAG_NONE)); |
519 EXPECT_EQ(123456789, buffer[0]); | 519 EXPECT_EQ(123456789, buffer[0]); |
520 | 520 |
521 // Now port 1 should no longer be readable. | 521 // Now port 1 should no longer be readable. |
522 waiter.Init(); | 522 waiter.Init(); |
523 hss = HandleSignalsState(); | 523 hss = HandleSignalsState(); |
524 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, | 524 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, |
525 mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 6, NULL)); | 525 mp->AddWaiter(1, &waiter, MOJO_HANDLE_SIGNAL_READABLE, 6, nullptr)); |
526 EXPECT_EQ(0u, hss.satisfied_signals); | 526 EXPECT_EQ(0u, hss.satisfied_signals); |
527 EXPECT_EQ(0u, hss.satisfiable_signals); | 527 EXPECT_EQ(0u, hss.satisfiable_signals); |
528 | 528 |
529 mp->Close(1); | 529 mp->Close(1); |
530 } | 530 } |
531 | 531 |
532 TEST(MessagePipeTest, ThreadedWaiting) { | 532 TEST(MessagePipeTest, ThreadedWaiting) { |
533 int32_t buffer[1]; | 533 int32_t buffer[1]; |
534 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); | 534 const uint32_t kBufferSize = static_cast<uint32_t>(sizeof(buffer)); |
535 | 535 |
536 MojoResult result; | 536 MojoResult result; |
537 uint32_t context; | 537 uint32_t context; |
538 | 538 |
539 // Write to wake up waiter waiting for read. | 539 // Write to wake up waiter waiting for read. |
540 { | 540 { |
541 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 541 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); |
542 test::SimpleWaiterThread thread(&result, &context); | 542 test::SimpleWaiterThread thread(&result, &context); |
543 | 543 |
544 thread.waiter()->Init(); | 544 thread.waiter()->Init(); |
545 ASSERT_EQ(MOJO_RESULT_OK, | 545 ASSERT_EQ(MOJO_RESULT_OK, |
546 mp->AddWaiter( | 546 mp->AddWaiter( |
547 1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1, NULL)); | 547 1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 1, nullptr)); |
548 thread.Start(); | 548 thread.Start(); |
549 | 549 |
550 buffer[0] = 123456789; | 550 buffer[0] = 123456789; |
551 // Write from port 0 (to port 1), which should wake up the waiter. | 551 // Write from port 0 (to port 1), which should wake up the waiter. |
552 EXPECT_EQ(MOJO_RESULT_OK, | 552 EXPECT_EQ(MOJO_RESULT_OK, |
553 mp->WriteMessage(0, | 553 mp->WriteMessage(0, |
554 UserPointer<const void>(buffer), | 554 UserPointer<const void>(buffer), |
555 kBufferSize, | 555 kBufferSize, |
556 NULL, | 556 nullptr, |
557 MOJO_WRITE_MESSAGE_FLAG_NONE)); | 557 MOJO_WRITE_MESSAGE_FLAG_NONE)); |
558 | 558 |
559 HandleSignalsState hss; | 559 HandleSignalsState hss; |
560 mp->RemoveWaiter(1, thread.waiter(), &hss); | 560 mp->RemoveWaiter(1, thread.waiter(), &hss); |
561 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 561 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
562 hss.satisfied_signals); | 562 hss.satisfied_signals); |
563 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, | 563 EXPECT_EQ(MOJO_HANDLE_SIGNAL_READABLE | MOJO_HANDLE_SIGNAL_WRITABLE, |
564 hss.satisfiable_signals); | 564 hss.satisfiable_signals); |
565 | 565 |
566 mp->Close(0); | 566 mp->Close(0); |
567 mp->Close(1); | 567 mp->Close(1); |
568 } // Joins |thread|. | 568 } // Joins |thread|. |
569 // The waiter should have woken up successfully. | 569 // The waiter should have woken up successfully. |
570 EXPECT_EQ(MOJO_RESULT_OK, result); | 570 EXPECT_EQ(MOJO_RESULT_OK, result); |
571 EXPECT_EQ(1u, context); | 571 EXPECT_EQ(1u, context); |
572 | 572 |
573 // Close to cancel waiter. | 573 // Close to cancel waiter. |
574 { | 574 { |
575 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 575 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); |
576 test::SimpleWaiterThread thread(&result, &context); | 576 test::SimpleWaiterThread thread(&result, &context); |
577 | 577 |
578 thread.waiter()->Init(); | 578 thread.waiter()->Init(); |
579 ASSERT_EQ(MOJO_RESULT_OK, | 579 ASSERT_EQ(MOJO_RESULT_OK, |
580 mp->AddWaiter( | 580 mp->AddWaiter( |
581 1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 2, NULL)); | 581 1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 2, nullptr)); |
582 thread.Start(); | 582 thread.Start(); |
583 | 583 |
584 // Close port 1 first -- this should result in the waiter being cancelled. | 584 // Close port 1 first -- this should result in the waiter being cancelled. |
585 mp->CancelAllWaiters(1); | 585 mp->CancelAllWaiters(1); |
586 mp->Close(1); | 586 mp->Close(1); |
587 | 587 |
588 // Port 1 is closed, so |Dispatcher::RemoveWaiter()| wouldn't call into the | 588 // Port 1 is closed, so |Dispatcher::RemoveWaiter()| wouldn't call into the |
589 // |MessagePipe| to remove any waiter. | 589 // |MessagePipe| to remove any waiter. |
590 | 590 |
591 mp->Close(0); | 591 mp->Close(0); |
592 } // Joins |thread|. | 592 } // Joins |thread|. |
593 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); | 593 EXPECT_EQ(MOJO_RESULT_CANCELLED, result); |
594 EXPECT_EQ(2u, context); | 594 EXPECT_EQ(2u, context); |
595 | 595 |
596 // Close to make waiter un-wake-up-able. | 596 // Close to make waiter un-wake-up-able. |
597 { | 597 { |
598 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); | 598 scoped_refptr<MessagePipe> mp(MessagePipe::CreateLocalLocal()); |
599 test::SimpleWaiterThread thread(&result, &context); | 599 test::SimpleWaiterThread thread(&result, &context); |
600 | 600 |
601 thread.waiter()->Init(); | 601 thread.waiter()->Init(); |
602 ASSERT_EQ(MOJO_RESULT_OK, | 602 ASSERT_EQ(MOJO_RESULT_OK, |
603 mp->AddWaiter( | 603 mp->AddWaiter( |
604 1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3, NULL)); | 604 1, thread.waiter(), MOJO_HANDLE_SIGNAL_READABLE, 3, nullptr)); |
605 thread.Start(); | 605 thread.Start(); |
606 | 606 |
607 // Close port 0 first -- this should wake the waiter up, since port 1 will | 607 // Close port 0 first -- this should wake the waiter up, since port 1 will |
608 // never be readable. | 608 // never be readable. |
609 mp->CancelAllWaiters(0); | 609 mp->CancelAllWaiters(0); |
610 mp->Close(0); | 610 mp->Close(0); |
611 | 611 |
612 HandleSignalsState hss; | 612 HandleSignalsState hss; |
613 mp->RemoveWaiter(1, thread.waiter(), &hss); | 613 mp->RemoveWaiter(1, thread.waiter(), &hss); |
614 EXPECT_EQ(0u, hss.satisfied_signals); | 614 EXPECT_EQ(0u, hss.satisfied_signals); |
615 EXPECT_EQ(0u, hss.satisfiable_signals); | 615 EXPECT_EQ(0u, hss.satisfiable_signals); |
616 | 616 |
617 mp->CancelAllWaiters(1); | 617 mp->CancelAllWaiters(1); |
618 mp->Close(1); | 618 mp->Close(1); |
619 } // Joins |thread|. | 619 } // Joins |thread|. |
620 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); | 620 EXPECT_EQ(MOJO_RESULT_FAILED_PRECONDITION, result); |
621 EXPECT_EQ(3u, context); | 621 EXPECT_EQ(3u, context); |
622 } | 622 } |
623 | 623 |
624 } // namespace | 624 } // namespace |
625 } // namespace system | 625 } // namespace system |
626 } // namespace mojo | 626 } // namespace mojo |
OLD | NEW |