Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / native_client_sdk / src / tests / nacl_io_test / jspipe_test.cc
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
3 // found in the LICENSE file.
4
5 #include <errno.h>
6 #include <fcntl.h>
7 #include <string.h>
8 #include <sys/ioctl.h>
9 #include <sys/select.h>
10 #include <sys/stat.h>
11 #include <sys/time.h>
12 #include <string>
13
14 #include "dev_fs_for_testing.h"
15 #include "fake_ppapi/fake_messaging_interface.h"
16 #include "gtest/gtest.h"
17 #include "nacl_io/devfs/dev_fs.h"
18 #include "nacl_io/filesystem.h"
19 #include "nacl_io/ioctl.h"
20 #include "nacl_io/kernel_intercept.h"
21 #include "nacl_io/kernel_proxy.h"
22 #include "nacl_io/osdirent.h"
23
24 using namespace nacl_io;
25
26 namespace {
27
28 class JSPipeTest : public ::testing::Test {
29  public:
30   void SetUp() {
31     ki_init(&kp_);
32     ASSERT_EQ(0, fs_.Access(Path("/jspipe1"), R_OK | W_OK));
33     ASSERT_EQ(EACCES, fs_.Access(Path("/jspipe1"), X_OK));
34     ASSERT_EQ(0, fs_.Open(Path("/jspipe1"), O_RDWR, &pipe_dev_));
35     ASSERT_NE(NULL_NODE, pipe_dev_.get());
36   }
37
38   void TearDown() { ki_uninit(); }
39
40  protected:
41   KernelProxy kp_;
42   DevFsForTesting fs_;
43   ScopedNode pipe_dev_;
44 };
45
46 TEST_F(JSPipeTest, InvalidIoctl) {
47   // 123 is not a valid ioctl request.
48   EXPECT_EQ(EINVAL, pipe_dev_->Ioctl(123));
49 }
50
51 TEST_F(JSPipeTest, JSPipeInput) {
52   // First we send some data into the pipe.  This is how messages
53   // from javascript are injected into the pipe nodes.
54   std::string message("hello, how are you?\n");
55   struct tioc_nacl_input_string packaged_message;
56   packaged_message.length = message.size();
57   packaged_message.buffer = message.data();
58   ASSERT_EQ(0, pipe_dev_->Ioctl(TIOCNACLINPUT, &packaged_message));
59
60   // Now we make buffer we'll read into.
61   // We fill the buffer and a backup buffer with arbitrary data
62   // and compare them after reading to make sure read doesn't
63   // clobber parts of the buffer it shouldn't.
64   int bytes_read;
65   char buffer[100];
66   char backup_buffer[100];
67   memset(buffer, 'a', sizeof(buffer));
68   memset(backup_buffer, 'a', sizeof(backup_buffer));
69
70   // We read a small chunk first to ensure it doesn't give us
71   // more than we ask for.
72   HandleAttr attrs;
73   ASSERT_EQ(0, pipe_dev_->Read(attrs, buffer, 5, &bytes_read));
74   EXPECT_EQ(5, bytes_read);
75   EXPECT_EQ(0, memcmp(message.data(), buffer, 5));
76   EXPECT_EQ(0, memcmp(buffer + 5, backup_buffer + 5, sizeof(buffer)-5));
77
78   // Now we ask for more data than is left in the pipe, to ensure
79   // it doesn't give us more than there is.
80   ASSERT_EQ(0, pipe_dev_->Read(attrs, buffer + 5, sizeof(buffer)-5,
81                                &bytes_read));
82   EXPECT_EQ(bytes_read, message.size() - 5);
83   EXPECT_EQ(0, memcmp(message.data(), buffer, message.size()));
84   EXPECT_EQ(0, memcmp(buffer + message.size(),
85                       backup_buffer + message.size(),
86                       100 - message.size()));
87 }
88
89 TEST_F(JSPipeTest, JSPipeOutput) {
90   const char* message = "hello";
91   const int message_len = strlen(message);
92
93   int bytes_written = 999;
94   HandleAttr attrs;
95   ASSERT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written));
96   ASSERT_EQ(message_len, bytes_written);
97
98   // Verify that the correct messages was sent via PostMessage.
99   FakeMessagingInterface* iface =
100       (FakeMessagingInterface*)fs_.ppapi()->GetMessagingInterface();
101   VarArrayInterface* array_iface = fs_.ppapi()->GetVarArrayInterface();
102   VarInterface* var_iface = fs_.ppapi()->GetVarInterface();
103   VarArrayBufferInterface* buffer_iface =
104       fs_.ppapi()->GetVarArrayBufferInterface();
105
106   // Verify that exaclty one message was sent of type PP_VARTYPE_ARRAY
107   ASSERT_EQ(1, iface->messages.size());
108   PP_Var array = iface->messages[0];
109   ASSERT_EQ(PP_VARTYPE_ARRAY, array.type);
110
111   // Verify that the array contains two element, the prefix,
112   // and an ArrayBuffer containing the message.
113   ASSERT_EQ(2, array_iface->GetLength(array));
114   PP_Var item0 = array_iface->Get(array, 0);
115   PP_Var item1 = array_iface->Get(array, 1);
116   ASSERT_EQ(PP_VARTYPE_STRING, item0.type);
117   ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, item1.type);
118   uint32_t len = 0;
119   const char* item0_string = var_iface->VarToUtf8(item0, &len);
120   ASSERT_STREQ("jspipe1", std::string(item0_string, len).c_str());
121   ASSERT_EQ(0, memcmp(message, buffer_iface->Map(item1), strlen(message)));
122   var_iface->Release(item0);
123   var_iface->Release(item1);
124 }
125
126 TEST_F(JSPipeTest, JSPipeOutputWithNulls) {
127   char message[20];
128   int message_len = sizeof(message);
129
130   // Construct a 20-byte  message containing the string 'hello' but with
131   // null chars on either end.
132   memset(message, 0 , message_len);
133   memcpy(message+10, "hello", 5);
134
135   int bytes_written = 999;
136   HandleAttr attrs;
137   EXPECT_EQ(0, pipe_dev_->Write(attrs, message, message_len, &bytes_written));
138   EXPECT_EQ(message_len, bytes_written);
139
140   // Verify that the correct messages was sent via PostMessage.
141   FakeMessagingInterface* iface =
142       (FakeMessagingInterface*)fs_.ppapi()->GetMessagingInterface();
143   VarArrayInterface* array_iface = fs_.ppapi()->GetVarArrayInterface();
144   VarInterface* var_iface = fs_.ppapi()->GetVarInterface();
145   VarArrayBufferInterface* buffer_iface =
146       fs_.ppapi()->GetVarArrayBufferInterface();
147
148   // Verify that exactly one message was sent of type PP_VARTYPE_ARRAY
149   EXPECT_EQ(1, iface->messages.size());
150   PP_Var array = iface->messages[0];
151   ASSERT_EQ(PP_VARTYPE_ARRAY, array.type);
152
153   // Verify that the array contains two element, the prefix,
154   // and an ArrayBuffer containing the message.
155   ASSERT_EQ(2, array_iface->GetLength(array));
156   PP_Var item0 = array_iface->Get(array, 0);
157   PP_Var item1 = array_iface->Get(array, 1);
158   ASSERT_EQ(PP_VARTYPE_STRING, item0.type);
159   ASSERT_EQ(PP_VARTYPE_ARRAY_BUFFER, item1.type);
160   uint32_t len = 0;
161   ASSERT_STREQ("jspipe1", var_iface->VarToUtf8(item0, &len));
162   ASSERT_EQ(0, memcmp(message, buffer_iface->Map(item1), strlen(message)));
163   var_iface->Release(item0);
164   var_iface->Release(item1);
165 }
166
167 static int ki_ioctl_wrapper(int fd, int request, ...) {
168   va_list ap;
169   va_start(ap, request);
170   int rtn = ki_ioctl(fd, request, ap);
171   va_end(ap);
172   return rtn;
173 }
174
175 static int JSPipeWrite(int fd, const char* string) {
176   struct tioc_nacl_input_string input;
177   input.buffer = string;
178   input.length = strlen(input.buffer);
179   return ki_ioctl_wrapper(fd, TIOCNACLINPUT, &input);
180 }
181
182 // Returns:
183 //   0 -> Not readable
184 //   1 -> Readable
185 //  -1 -> Error occured
186 static int IsReadable(int fd) {
187   struct timeval timeout = {0, 0};
188   fd_set readfds;
189   fd_set errorfds;
190   FD_ZERO(&readfds);
191   FD_ZERO(&errorfds);
192   FD_SET(fd, &readfds);
193   FD_SET(fd, &errorfds);
194   int rtn = ki_select(fd + 1, &readfds, NULL, &errorfds, &timeout);
195   if (rtn == 0)
196     return 0;  // not readable
197   if (rtn != 1)
198     return -1;  // error
199   if (FD_ISSET(fd, &errorfds))
200     return -2;  // error
201   if (!FD_ISSET(fd, &readfds))
202     return -3;  // error
203   return 1;     // readable
204 }
205
206 TEST_F(JSPipeTest, JSPipeSelect) {
207   struct timeval timeout;
208   fd_set readfds;
209   fd_set writefds;
210   fd_set errorfds;
211
212   int pipe_fd = ki_open("/dev/jspipe1", O_RDONLY);
213   ASSERT_GT(pipe_fd, 0) << "jspipe1 open failed: " << errno;
214
215   FD_ZERO(&readfds);
216   FD_ZERO(&errorfds);
217   FD_SET(pipe_fd, &readfds);
218   FD_SET(pipe_fd, &errorfds);
219   // 10 millisecond timeout
220   timeout.tv_sec = 0;
221   timeout.tv_usec = 10 * 1000;
222   // Should timeout when no input is available.
223   int rtn = ki_select(pipe_fd + 1, &readfds, NULL, &errorfds, &timeout);
224   ASSERT_EQ(0, rtn) << "select failed: " << rtn << " err=" << strerror(errno);
225   ASSERT_FALSE(FD_ISSET(pipe_fd, &readfds));
226   ASSERT_FALSE(FD_ISSET(pipe_fd, &errorfds));
227
228   FD_ZERO(&readfds);
229   FD_ZERO(&writefds);
230   FD_ZERO(&errorfds);
231   FD_SET(pipe_fd, &readfds);
232   FD_SET(pipe_fd, &writefds);
233   FD_SET(pipe_fd, &errorfds);
234   // Pipe should be writable on startup.
235   rtn = ki_select(pipe_fd + 1, &readfds, &writefds, &errorfds, NULL);
236   ASSERT_EQ(1, rtn);
237   ASSERT_TRUE(FD_ISSET(pipe_fd, &writefds));
238   ASSERT_FALSE(FD_ISSET(pipe_fd, &readfds));
239   ASSERT_FALSE(FD_ISSET(pipe_fd, &errorfds));
240
241   // Send 4 bytes to the pipe
242   ASSERT_EQ(0, JSPipeWrite(pipe_fd, "test"));
243
244   // Pipe should now be readable
245   ASSERT_EQ(1, IsReadable(pipe_fd));
246
247   ki_close(pipe_fd);
248 }
249
250 }