OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 <errno.h> | 5 #include <errno.h> |
6 #include <fcntl.h> | 6 #include <fcntl.h> |
7 #include <string.h> | 7 #include <string.h> |
8 #include <sys/ioctl.h> | 8 #include <sys/ioctl.h> |
9 #include <sys/select.h> | 9 #include <sys/select.h> |
10 #include <sys/stat.h> | 10 #include <sys/stat.h> |
11 #include <sys/time.h> | 11 #include <sys/time.h> |
12 #include <string> | 12 #include <string> |
13 | 13 |
14 #include "dev_fs_for_testing.h" | 14 #include "dev_fs_for_testing.h" |
15 #include "fake_ppapi/fake_messaging_interface.h" | 15 #include "fake_ppapi/fake_messaging_interface.h" |
16 #include "gtest/gtest.h" | 16 #include "gtest/gtest.h" |
17 #include "nacl_io/devfs/dev_fs.h" | 17 #include "nacl_io/devfs/dev_fs.h" |
18 #include "nacl_io/filesystem.h" | 18 #include "nacl_io/filesystem.h" |
19 #include "nacl_io/ioctl.h" | 19 #include "nacl_io/ioctl.h" |
20 #include "nacl_io/kernel_intercept.h" | 20 #include "nacl_io/kernel_intercept.h" |
21 #include "nacl_io/kernel_proxy.h" | 21 #include "nacl_io/kernel_proxy.h" |
22 #include "nacl_io/osdirent.h" | 22 #include "nacl_io/osdirent.h" |
23 | 23 |
24 using namespace nacl_io; | 24 using namespace nacl_io; |
25 | 25 |
26 namespace { | 26 namespace { |
27 | 27 |
| 28 // Helper function for calling ki_ioctl without having |
| 29 // to construct a va_list. |
| 30 int ki_ioctl_wrapper(int fd, int request, ...) { |
| 31 va_list ap; |
| 32 va_start(ap, request); |
| 33 int rtn = ki_ioctl(fd, request, ap); |
| 34 va_end(ap); |
| 35 return rtn; |
| 36 } |
| 37 |
| 38 // Helper function for converting PP_Var to C++ string |
| 39 std::string VarToString(VarInterface* var_iface, PP_Var var) { |
| 40 EXPECT_EQ(PP_VARTYPE_STRING, var.type); |
| 41 uint32_t len = 0; |
| 42 const char* str = var_iface->VarToUtf8(var, &len); |
| 43 return std::string(str, len); |
| 44 } |
| 45 |
| 46 PP_Var VarFromCStr(VarInterface* iface, const char* string) { |
| 47 return iface->VarFromUtf8(string, strlen(string)); |
| 48 } |
| 49 |
| 50 // Helper function for creating message in the format expected by jspipe |
| 51 // nodes: [ name, payload ] |
| 52 PP_Var CreatePipeMessage(PepperInterface* ppapi, const char* pipe, |
| 53 const char* operation, PP_Var payload) { |
| 54 VarInterface* var_iface = ppapi->GetVarInterface(); |
| 55 VarDictionaryInterface* dict_iface = ppapi->GetVarDictionaryInterface(); |
| 56 |
| 57 // Create a two element array containing the name of the message |
| 58 // as the first element. Its up to the caller the then set the |
| 59 // second array element. |
| 60 PP_Var message = dict_iface->Create(); |
| 61 PP_Var pipe_var = VarFromCStr(var_iface, pipe); |
| 62 PP_Var operation_var = VarFromCStr(var_iface, operation); |
| 63 PP_Var pipe_key = VarFromCStr(var_iface, "pipe"); |
| 64 PP_Var payload_key = VarFromCStr(var_iface, "payload"); |
| 65 PP_Var operation_key = VarFromCStr(var_iface, "operation"); |
| 66 dict_iface->Set(message, pipe_key, pipe_var); |
| 67 dict_iface->Set(message, operation_key, operation_var); |
| 68 dict_iface->Set(message, payload_key, payload); |
| 69 var_iface->Release(pipe_var); |
| 70 var_iface->Release(operation_var); |
| 71 var_iface->Release(payload); |
| 72 var_iface->Release(pipe_key); |
| 73 var_iface->Release(payload_key); |
| 74 var_iface->Release(operation_key); |
| 75 return message; |
| 76 } |
| 77 |
| 78 // Helper function for creating "ack" message in format expected |
| 79 // by jspipe nodes. |
| 80 PP_Var CreateAckMessage(PepperInterface* ppapi, const char* pipe, |
| 81 int32_t count) { |
| 82 return CreatePipeMessage(ppapi, pipe, "ack", PP_MakeInt32(count)); |
| 83 } |
| 84 |
| 85 // Helper function for creating "write" message in format expected |
| 86 // by jspipe nodes. |
| 87 PP_Var CreateWriteMessage(PepperInterface* ppapi, |
| 88 const char* pipe, |
| 89 const char* string, |
| 90 int length=-1) { |
| 91 VarArrayBufferInterface* buffer_iface = ppapi->GetVarArrayBufferInterface(); |
| 92 |
| 93 if (length == -1) |
| 94 length = strlen(string); |
| 95 |
| 96 PP_Var buffer = buffer_iface->Create(length); |
| 97 memcpy(buffer_iface->Map(buffer), string, length); |
| 98 buffer_iface->Unmap(buffer); |
| 99 |
| 100 return CreatePipeMessage(ppapi, pipe, "write", buffer); |
| 101 } |
| 102 |
28 class JSPipeTest : public ::testing::Test { | 103 class JSPipeTest : public ::testing::Test { |
29 public: | 104 public: |
30 JSPipeTest() : fs_(&pepper_) {} | |
31 | |
32 void SetUp() { | 105 void SetUp() { |
33 ASSERT_EQ(0, ki_push_state_for_testing()); | 106 ASSERT_EQ(0, ki_push_state_for_testing()); |
34 ASSERT_EQ(0, ki_init(&kp_)); | 107 ASSERT_EQ(0, ki_init_interface(&kp_, &ppapi_)); |
| 108 } |
| 109 |
| 110 void TearDown() { |
| 111 ki_uninit(); |
| 112 } |
| 113 |
| 114 protected: |
| 115 FakePepperInterface ppapi_; |
| 116 KernelProxy kp_; |
| 117 }; |
| 118 |
| 119 class JSPipeNodeTest : public ::testing::Test { |
| 120 public: |
| 121 JSPipeNodeTest() : fs_(&ppapi_) {} |
| 122 |
| 123 void SetUp() { |
| 124 name_ = "jspipe1"; |
35 ASSERT_EQ(0, fs_.Access(Path("/jspipe1"), R_OK | W_OK)); | 125 ASSERT_EQ(0, fs_.Access(Path("/jspipe1"), R_OK | W_OK)); |
36 ASSERT_EQ(EACCES, fs_.Access(Path("/jspipe1"), X_OK)); | 126 ASSERT_EQ(EACCES, fs_.Access(Path("/jspipe1"), X_OK)); |
37 ASSERT_EQ(0, fs_.Open(Path("/jspipe1"), O_RDWR, &pipe_dev_)); | 127 ASSERT_EQ(0, fs_.Open(Path("/jspipe1"), O_RDWR, &pipe_dev_)); |
38 ASSERT_NE(NULL_NODE, pipe_dev_.get()); | 128 ASSERT_NE(NULL_NODE, pipe_dev_.get()); |
39 } | 129 } |
40 | 130 |
41 void TearDown() { ki_uninit(); } | 131 /** |
| 132 * Create a PP_Var message in the same way that we expect |
| 133 * JavaScript code to, and send it to the pipe using ioctl() |
| 134 */ |
| 135 int JSPipeInject(const char* string, int length=-1) { |
| 136 PP_Var message = CreateWriteMessage(&ppapi_, name_, string, length); |
| 137 |
| 138 // Send the message via ioctl |
| 139 int rtn = pipe_dev_->Ioctl(NACL_IOC_HANDLEMESSAGE, &message); |
| 140 |
| 141 // Release message |
| 142 ppapi_.GetVarInterface()->Release(message); |
| 143 return rtn; |
| 144 } |
| 145 |
| 146 int JSPipeInjectAck(int32_t count) { |
| 147 PP_Var message = CreateAckMessage(&ppapi_, name_, count); |
| 148 |
| 149 // Send the message via ioctl |
| 150 int rtn = pipe_dev_->Ioctl(NACL_IOC_HANDLEMESSAGE, &message); |
| 151 |
| 152 // Release message |
| 153 ppapi_.GetVarInterface()->Release(message); |
| 154 return rtn; |
| 155 } |
| 156 |
| 157 // Verify the contents of the jspipe mesage, which should be |
| 158 // {'<pipe_name>' : ['<command_name>', payload] } |
| 159 void VerifyPipeMessage(PP_Var message, |
| 160 const char* pipe_name, |
| 161 const char* operation, |
| 162 const char* payload, |
| 163 int payload_length, |
| 164 int32_t int_payload=0) { |
| 165 VarArrayInterface* array_iface = ppapi_.GetVarArrayInterface(); |
| 166 VarDictionaryInterface* dict_iface = ppapi_.GetVarDictionaryInterface(); |
| 167 VarInterface* var_iface = ppapi_.GetVarInterface(); |
| 168 VarArrayBufferInterface* buffer_iface = ppapi_.GetVarArrayBufferInterface(); |
| 169 |
| 170 // Verify we have a dictionary with 3 keys |
| 171 ASSERT_EQ(PP_VARTYPE_DICTIONARY, message.type); |
| 172 PP_Var keys = dict_iface->GetKeys(message); |
| 173 ASSERT_EQ(PP_VARTYPE_ARRAY, keys.type); |
| 174 ASSERT_EQ(3, array_iface->GetLength(keys)); |
| 175 var_iface->Release(keys); |
| 176 |
| 177 // Verify the keys |
| 178 PP_Var key1 = VarFromCStr(var_iface, "pipe"); |
| 179 PP_Var key2 = VarFromCStr(var_iface, "operation"); |
| 180 PP_Var key3 = VarFromCStr(var_iface, "payload"); |
| 181 |
| 182 // Verify pipe name and operation values |
| 183 PP_Var value1 = dict_iface->Get(message, key1); |
| 184 ASSERT_STREQ(pipe_name, VarToString(var_iface, value1).c_str()); |
| 185 var_iface->Release(value1); |
| 186 var_iface->Release(key1); |
| 187 |
| 188 PP_Var value2 = dict_iface->Get(message, key2); |
| 189 ASSERT_STREQ(operation, VarToString(var_iface, value2).c_str()); |
| 190 var_iface->Release(value2); |
| 191 var_iface->Release(key2); |
| 192 |
| 193 // Verify the payload |
| 194 PP_Var payload_var = dict_iface->Get(message, key3); |
| 195 if (payload != NULL) { |
| 196 ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, payload_var.type); |
| 197 ASSERT_EQ(0, memcmp(payload, buffer_iface->Map(payload_var), |
| 198 payload_length)); |
| 199 } else { |
| 200 ASSERT_EQ(PP_VARTYPE_INT32, payload_var.type); |
| 201 ASSERT_EQ(int_payload, payload_var.value.as_int); |
| 202 } |
| 203 var_iface->Release(key3); |
| 204 var_iface->Release(payload_var); |
| 205 } |
42 | 206 |
43 protected: | 207 protected: |
44 KernelProxy kp_; | 208 FakePepperInterface ppapi_; |
45 FakePepperInterface pepper_; | |
46 DevFsForTesting fs_; | 209 DevFsForTesting fs_; |
47 ScopedNode pipe_dev_; | 210 ScopedNode pipe_dev_; |
| 211 const char* name_; |
48 }; | 212 }; |
49 | 213 |
50 TEST_F(JSPipeTest, InvalidIoctl) { | 214 TEST(JSPipeTestBasic, MissingPepper) { |
| 215 // Create a devfs filesystem without giving it any Pepper implemenation. |
| 216 TypedFsFactory<DevFs> factory; |
| 217 ScopedFilesystem fs; |
| 218 FsInitArgs args(1); |
| 219 factory.CreateFilesystem(args, &fs); |
| 220 ScopedNode pipe_dev; |
| 221 ASSERT_EQ(0, fs->Open(Path("/jspipe1"), O_RDWR, &pipe_dev)); |
| 222 |
| 223 // Writing to a pipe should return EIO because Pepper is missing. |
| 224 HandleAttr attrs; |
| 225 int written = -1; |
| 226 ASSERT_EQ(EIO, pipe_dev->Write(attrs, "test", 4, &written)); |
| 227 } |
| 228 |
| 229 TEST_F(JSPipeNodeTest, InvalidIoctl) { |
51 // 123 is not a valid ioctl request. | 230 // 123 is not a valid ioctl request. |
52 EXPECT_EQ(EINVAL, pipe_dev_->Ioctl(123)); | 231 EXPECT_EQ(EINVAL, pipe_dev_->Ioctl(123)); |
53 } | 232 } |
54 | 233 |
55 TEST_F(JSPipeTest, JSPipeInput) { | 234 TEST_F(JSPipeNodeTest, JSPipeInput) { |
| 235 std::string message("hello, how are you?\n"); |
| 236 |
56 // First we send some data into the pipe. This is how messages | 237 // First we send some data into the pipe. This is how messages |
57 // from javascript are injected into the pipe nodes. | 238 // from javascript are injected into the pipe nodes. |
58 std::string message("hello, how are you?\n"); | 239 ASSERT_EQ(0, JSPipeInject(message.c_str())); |
59 struct tioc_nacl_input_string packaged_message; | |
60 packaged_message.length = message.size(); | |
61 packaged_message.buffer = message.data(); | |
62 ASSERT_EQ(0, pipe_dev_->Ioctl(TIOCNACLINPUT, &packaged_message)); | |
63 | 240 |
64 // Now we make buffer we'll read into. | 241 // Now we make buffer we'll read into. |
65 // We fill the buffer and a backup buffer with arbitrary data | 242 // We fill the buffer and a backup buffer with arbitrary data |
66 // and compare them after reading to make sure read doesn't | 243 // and compare them after reading to make sure read doesn't |
67 // clobber parts of the buffer it shouldn't. | 244 // clobber parts of the buffer it shouldn't. |
68 int bytes_read; | 245 int bytes_read; |
69 char buffer[100]; | 246 char buffer[100]; |
70 char backup_buffer[100]; | 247 char backup_buffer[100]; |
71 memset(buffer, 'a', sizeof(buffer)); | 248 memset(buffer, 'a', sizeof(buffer)); |
72 memset(backup_buffer, 'a', sizeof(backup_buffer)); | 249 memset(backup_buffer, 'a', sizeof(backup_buffer)); |
(...skipping 10 matching lines...) Expand all Loading... |
83 // it doesn't give us more than there is. | 260 // it doesn't give us more than there is. |
84 ASSERT_EQ(0, pipe_dev_->Read(attrs, buffer + 5, sizeof(buffer)-5, | 261 ASSERT_EQ(0, pipe_dev_->Read(attrs, buffer + 5, sizeof(buffer)-5, |
85 &bytes_read)); | 262 &bytes_read)); |
86 EXPECT_EQ(bytes_read, message.size() - 5); | 263 EXPECT_EQ(bytes_read, message.size() - 5); |
87 EXPECT_EQ(0, memcmp(message.data(), buffer, message.size())); | 264 EXPECT_EQ(0, memcmp(message.data(), buffer, message.size())); |
88 EXPECT_EQ(0, memcmp(buffer + message.size(), | 265 EXPECT_EQ(0, memcmp(buffer + message.size(), |
89 backup_buffer + message.size(), | 266 backup_buffer + message.size(), |
90 100 - message.size())); | 267 100 - message.size())); |
91 } | 268 } |
92 | 269 |
93 TEST_F(JSPipeTest, JSPipeOutput) { | 270 TEST_F(JSPipeNodeTest, JSPipeOutput) { |
94 const char* message = "hello"; | 271 std::string message("hello"); |
95 const int message_len = strlen(message); | |
96 | 272 |
97 int bytes_written = 999; | 273 int bytes_written = 999; |
98 HandleAttr attrs; | 274 HandleAttr attrs; |
99 ASSERT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written)); | 275 ASSERT_EQ(0, pipe_dev_->Write(attrs, message.c_str(), message.size(), |
100 ASSERT_EQ(message_len, bytes_written); | 276 &bytes_written)); |
| 277 ASSERT_EQ(message.size(), bytes_written); |
101 | 278 |
102 // Verify that the correct messages was sent via PostMessage. | |
103 FakeMessagingInterface* iface = | 279 FakeMessagingInterface* iface = |
104 (FakeMessagingInterface*)fs_.ppapi()->GetMessagingInterface(); | 280 (FakeMessagingInterface*)ppapi_.GetMessagingInterface(); |
105 VarArrayInterface* array_iface = fs_.ppapi()->GetVarArrayInterface(); | |
106 VarInterface* var_iface = fs_.ppapi()->GetVarInterface(); | |
107 VarArrayBufferInterface* buffer_iface = | |
108 fs_.ppapi()->GetVarArrayBufferInterface(); | |
109 | 281 |
110 // Verify that exaclty one message was sent of type PP_VARTYPE_ARRAY | 282 // Verify that exactly one message sent. |
111 ASSERT_EQ(1, iface->messages.size()); | 283 ASSERT_EQ(1, iface->messages.size()); |
112 PP_Var array = iface->messages[0]; | 284 PP_Var message_var = iface->messages[0]; |
113 ASSERT_EQ(PP_VARTYPE_ARRAY, array.type); | |
114 | 285 |
115 // Verify that the array contains two element, the prefix, | 286 // Verify the content of the message. |
116 // and an ArrayBuffer containing the message. | 287 VerifyPipeMessage(message_var, "jspipe1", "write", message.c_str(), |
117 ASSERT_EQ(2, array_iface->GetLength(array)); | 288 message.size()); |
118 PP_Var item0 = array_iface->Get(array, 0); | |
119 PP_Var item1 = array_iface->Get(array, 1); | |
120 ASSERT_EQ(PP_VARTYPE_STRING, item0.type); | |
121 ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, item1.type); | |
122 uint32_t len = 0; | |
123 const char* item0_string = var_iface->VarToUtf8(item0, &len); | |
124 ASSERT_STREQ("jspipe1", std::string(item0_string, len).c_str()); | |
125 ASSERT_EQ(0, memcmp(message, buffer_iface->Map(item1), strlen(message))); | |
126 var_iface->Release(item0); | |
127 var_iface->Release(item1); | |
128 } | 289 } |
129 | 290 |
130 TEST_F(JSPipeTest, JSPipeOutputWithNulls) { | 291 TEST_F(JSPipeNodeTest, JSPipeOutputWithNulls) { |
131 char message[20]; | 292 char message[20]; |
132 int message_len = sizeof(message); | 293 int message_len = sizeof(message); |
133 | 294 |
134 // Construct a 20-byte message containing the string 'hello' but with | 295 // Construct a 20-byte message containing the string 'hello' but with |
135 // null chars on either end. | 296 // null chars on either end. |
136 memset(message, 0 , message_len); | 297 memset(message, 0 , message_len); |
137 memcpy(message+10, "hello", 5); | 298 memcpy(message+10, "hello", 5); |
138 | 299 |
139 int bytes_written = 999; | 300 int bytes_written = 999; |
140 HandleAttr attrs; | 301 HandleAttr attrs; |
141 EXPECT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written)); | 302 EXPECT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written)); |
142 EXPECT_EQ(message_len, bytes_written); | 303 EXPECT_EQ(message_len, bytes_written); |
143 | 304 |
144 // Verify that the correct messages was sent via PostMessage. | 305 // Verify that the correct messages was sent via PostMessage. |
145 FakeMessagingInterface* iface = | 306 FakeMessagingInterface* iface = |
146 (FakeMessagingInterface*)fs_.ppapi()->GetMessagingInterface(); | 307 (FakeMessagingInterface*)ppapi_.GetMessagingInterface(); |
147 VarArrayInterface* array_iface = fs_.ppapi()->GetVarArrayInterface(); | |
148 VarInterface* var_iface = fs_.ppapi()->GetVarInterface(); | |
149 VarArrayBufferInterface* buffer_iface = | |
150 fs_.ppapi()->GetVarArrayBufferInterface(); | |
151 | 308 |
152 // Verify that exactly one message was sent of type PP_VARTYPE_ARRAY | 309 // Verify that exaclty one message sent. |
153 EXPECT_EQ(1, iface->messages.size()); | 310 ASSERT_EQ(1, iface->messages.size()); |
154 PP_Var array = iface->messages[0]; | 311 PP_Var message_var = iface->messages[0]; |
155 ASSERT_EQ(PP_VARTYPE_ARRAY, array.type); | |
156 | 312 |
157 // Verify that the array contains two element, the prefix, | 313 // Verify the content of the message. |
158 // and an ArrayBuffer containing the message. | 314 VerifyPipeMessage(message_var, "jspipe1", "write", message, message_len); |
159 ASSERT_EQ(2, array_iface->GetLength(array)); | |
160 PP_Var item0 = array_iface->Get(array, 0); | |
161 PP_Var item1 = array_iface->Get(array, 1); | |
162 ASSERT_EQ(PP_VARTYPE_STRING, item0.type); | |
163 ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, item1.type); | |
164 uint32_t len = 0; | |
165 ASSERT_STREQ("jspipe1", var_iface->VarToUtf8(item0, &len)); | |
166 ASSERT_EQ(0, memcmp(message, buffer_iface->Map(item1), strlen(message))); | |
167 var_iface->Release(item0); | |
168 var_iface->Release(item1); | |
169 } | 315 } |
170 | 316 |
171 static int ki_ioctl_wrapper(int fd, int request, ...) { | 317 #define CHUNK_SIZE 678 |
172 va_list ap; | 318 TEST_F(JSPipeNodeTest, JSPipeOutputBuffer) { |
173 va_start(ap, request); | 319 int ospace_orig = -1; |
174 int rtn = ki_ioctl(fd, request, ap); | 320 ASSERT_EQ(0, pipe_dev_->Ioctl(NACL_IOC_PIPE_GETOSPACE, &ospace_orig)); |
175 va_end(ap); | 321 ASSERT_GT(ospace_orig, 0); |
176 return rtn; | 322 |
| 323 HandleAttr attrs; |
| 324 attrs.flags = O_NONBLOCK; |
| 325 char* message = (char*)malloc(CHUNK_SIZE); |
| 326 |
| 327 // Keep writing data until we block. |
| 328 int total_written = 0; |
| 329 while (1) { |
| 330 int bytes_written; |
| 331 // Write some data |
| 332 int rtn = pipe_dev_->Write(attrs, message, CHUNK_SIZE, &bytes_written); |
| 333 if (rtn != 0) { |
| 334 ASSERT_EQ(EWOULDBLOCK, rtn); |
| 335 int ospace = -1; |
| 336 ASSERT_EQ(0, pipe_dev_->Ioctl(NACL_IOC_PIPE_GETOSPACE, &ospace)); |
| 337 ASSERT_EQ(0, ospace); |
| 338 ASSERT_EQ(total_written, ospace_orig); |
| 339 break; |
| 340 } |
| 341 total_written += bytes_written; |
| 342 } |
| 343 |
| 344 // At this point writes should always block |
| 345 int bytes_written; |
| 346 int rtn = pipe_dev_->Write(attrs, message, CHUNK_SIZE, &bytes_written); |
| 347 ASSERT_EQ(EWOULDBLOCK, rtn); |
| 348 |
| 349 // Now inject and ACK message from JavaScript. |
| 350 ASSERT_EQ(0, JSPipeInjectAck(10)); |
| 351 |
| 352 // Now it should be possible to write 10 bytes to the pipe. |
| 353 rtn = pipe_dev_->Write(attrs, message, CHUNK_SIZE, &bytes_written); |
| 354 ASSERT_EQ(0, rtn); |
| 355 ASSERT_EQ(10, bytes_written); |
| 356 |
| 357 free(message); |
177 } | 358 } |
178 | 359 |
179 static int JSPipeWrite(int fd, const char* string) { | 360 TEST_F(JSPipeNodeTest, JSPipeInputBuffer) { |
180 struct tioc_nacl_input_string input; | 361 char* message = (char*)malloc(CHUNK_SIZE); |
181 input.buffer = string; | 362 memset(message, 1, CHUNK_SIZE); |
182 input.length = strlen(input.buffer); | 363 |
183 return ki_ioctl_wrapper(fd, TIOCNACLINPUT, &input); | 364 int ispace_orig = -1; |
| 365 ASSERT_EQ(0, pipe_dev_->Ioctl(NACL_IOC_PIPE_GETISPACE, &ispace_orig)); |
| 366 |
| 367 // Keep injecting data until the ioctl fails |
| 368 int total_written = 0; |
| 369 while (1) { |
| 370 int rtn = JSPipeInject(message, CHUNK_SIZE); |
| 371 if (rtn != 0) { |
| 372 ASSERT_LT(total_written, ispace_orig); |
| 373 ASSERT_GT(total_written, ispace_orig - CHUNK_SIZE - 1); |
| 374 break; |
| 375 } |
| 376 total_written += CHUNK_SIZE; |
| 377 } |
| 378 |
| 379 int ispace = -1; |
| 380 ASSERT_EQ(0, pipe_dev_->Ioctl(NACL_IOC_PIPE_GETISPACE, &ispace)); |
| 381 ASSERT_EQ(0, ispace); |
| 382 |
| 383 // Check that no messages have thus far been sent to JavaScript |
| 384 FakeMessagingInterface* iface = |
| 385 (FakeMessagingInterface*)ppapi_.GetMessagingInterface(); |
| 386 ASSERT_EQ(0, iface->messages.size()); |
| 387 |
| 388 // Read some data from the pipe, which should trigger an ack message |
| 389 int bytes_read = -1; |
| 390 HandleAttr attrs; |
| 391 ASSERT_EQ(0, pipe_dev_->Read(attrs, message, 5, &bytes_read)); |
| 392 ASSERT_EQ(5, bytes_read); |
| 393 |
| 394 // Verify that an ack was sent to JavaScript |
| 395 ASSERT_EQ(1, iface->messages.size()); |
| 396 PP_Var message_var = iface->messages[0]; |
| 397 VerifyPipeMessage(message_var, "jspipe1", "ack", NULL, 0, 5); |
184 } | 398 } |
185 | 399 |
186 // Returns: | 400 // Returns: |
187 // 0 -> Not readable | 401 // 0 -> Not readable |
188 // 1 -> Readable | 402 // 1 -> Readable |
189 // -1 -> Error occured | 403 // -1 -> Error occured |
190 static int IsReadable(int fd) { | 404 int IsReadable(int fd) { |
191 struct timeval timeout = {0, 0}; | 405 struct timeval timeout = {0, 0}; |
192 fd_set readfds; | 406 fd_set readfds; |
193 fd_set errorfds; | 407 fd_set errorfds; |
194 FD_ZERO(&readfds); | 408 FD_ZERO(&readfds); |
195 FD_ZERO(&errorfds); | 409 FD_ZERO(&errorfds); |
196 FD_SET(fd, &readfds); | 410 FD_SET(fd, &readfds); |
197 FD_SET(fd, &errorfds); | 411 FD_SET(fd, &errorfds); |
198 int rtn = ki_select(fd + 1, &readfds, NULL, &errorfds, &timeout); | 412 int rtn = ki_select(fd + 1, &readfds, NULL, &errorfds, &timeout); |
199 if (rtn == 0) | 413 if (rtn == 0) |
200 return 0; // not readable | 414 return 0; // not readable |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
235 FD_SET(pipe_fd, &readfds); | 449 FD_SET(pipe_fd, &readfds); |
236 FD_SET(pipe_fd, &writefds); | 450 FD_SET(pipe_fd, &writefds); |
237 FD_SET(pipe_fd, &errorfds); | 451 FD_SET(pipe_fd, &errorfds); |
238 // Pipe should be writable on startup. | 452 // Pipe should be writable on startup. |
239 rtn = ki_select(pipe_fd + 1, &readfds, &writefds, &errorfds, NULL); | 453 rtn = ki_select(pipe_fd + 1, &readfds, &writefds, &errorfds, NULL); |
240 ASSERT_EQ(1, rtn); | 454 ASSERT_EQ(1, rtn); |
241 ASSERT_TRUE(FD_ISSET(pipe_fd, &writefds)); | 455 ASSERT_TRUE(FD_ISSET(pipe_fd, &writefds)); |
242 ASSERT_FALSE(FD_ISSET(pipe_fd, &readfds)); | 456 ASSERT_FALSE(FD_ISSET(pipe_fd, &readfds)); |
243 ASSERT_FALSE(FD_ISSET(pipe_fd, &errorfds)); | 457 ASSERT_FALSE(FD_ISSET(pipe_fd, &errorfds)); |
244 | 458 |
245 // Send 4 bytes to the pipe | 459 // Send 4 bytes to the pipe via ioctl |
246 ASSERT_EQ(0, JSPipeWrite(pipe_fd, "test")); | 460 PP_Var message = CreateWriteMessage(&ppapi_, "jspipe1", "test"); |
| 461 ASSERT_EQ(0, ki_ioctl_wrapper(pipe_fd, NACL_IOC_HANDLEMESSAGE, &message)); |
| 462 ppapi_.GetVarInterface()->Release(message); |
247 | 463 |
248 // Pipe should now be readable | 464 // Pipe should now be readable |
249 ASSERT_EQ(1, IsReadable(pipe_fd)); | 465 ASSERT_EQ(1, IsReadable(pipe_fd)); |
250 | 466 |
251 ki_close(pipe_fd); | 467 ki_close(pipe_fd); |
252 } | 468 } |
253 | 469 |
254 } | 470 } |
OLD | NEW |