kernel_wrap_test.cc revision 68043e1e95eeb07d5cae7aca370b26518b0867d6
1// Copyright (c) 2013 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 <string>
6#include <vector>
7
8#include "gtest/gtest.h"
9#include "kernel_proxy_mock.h"
10#include "nacl_io/kernel_intercept.h"
11#include "nacl_io/kernel_wrap.h"
12#include "nacl_io/ossocket.h"
13#include "nacl_io/ostermios.h"
14
15using namespace nacl_io;
16
17using ::testing::_;
18using ::testing::Return;
19using ::testing::StrEq;
20
21namespace {
22
23static const int DUMMY_FD = 5678;
24
25#define COMPARE_FIELD(f) \
26  if (arg->f != statbuf->f) { \
27    *result_listener << "mismatch of field \""#f"\". " \
28      "expected: " << statbuf->f << \
29      " actual: " << arg->f; \
30    return false; \
31  }
32
33MATCHER_P(IsEqualToStatbuf, statbuf, "") {
34  COMPARE_FIELD(st_dev);
35  COMPARE_FIELD(st_ino);
36  COMPARE_FIELD(st_mode);
37  COMPARE_FIELD(st_nlink);
38  COMPARE_FIELD(st_uid);
39  COMPARE_FIELD(st_gid);
40  COMPARE_FIELD(st_rdev);
41  COMPARE_FIELD(st_size);
42  COMPARE_FIELD(st_atime);
43  COMPARE_FIELD(st_mtime);
44  COMPARE_FIELD(st_ctime);
45  return true;
46}
47
48#undef COMPARE_FIELD
49
50ACTION_P(SetStat, statbuf) {
51  memset(arg1, 0, sizeof(struct stat));
52  arg1->st_dev = statbuf->st_dev;
53  arg1->st_ino = statbuf->st_ino;
54  arg1->st_mode = statbuf->st_mode;
55  arg1->st_nlink = statbuf->st_nlink;
56  arg1->st_uid = statbuf->st_uid;
57  arg1->st_gid = statbuf->st_gid;
58  arg1->st_rdev = statbuf->st_rdev;
59  arg1->st_size = statbuf->st_size;
60  arg1->st_atime = statbuf->st_atime;
61  arg1->st_mtime = statbuf->st_mtime;
62  arg1->st_ctime = statbuf->st_ctime;
63  return 0;
64}
65
66void MakeDummyStatbuf(struct stat* statbuf) {
67  memset(&statbuf[0], 0, sizeof(struct stat));
68  statbuf->st_dev = 1;
69  statbuf->st_ino = 2;
70  statbuf->st_mode = 3;
71  statbuf->st_nlink = 4;
72  statbuf->st_uid = 5;
73  statbuf->st_gid = 6;
74  statbuf->st_rdev = 7;
75  statbuf->st_size = 8;
76  statbuf->st_atime = 9;
77  statbuf->st_mtime = 10;
78  statbuf->st_ctime = 11;
79}
80
81const uid_t kDummyUid = 1001;
82const gid_t kDummyGid = 1002;
83
84class KernelWrapTest : public ::testing::Test {
85 public:
86  KernelWrapTest() {
87    // Initializing the KernelProxy opens stdin/stdout/stderr.
88    EXPECT_CALL(mock, open(_, _))
89      .WillOnce(Return(0))
90      .WillOnce(Return(1))
91      .WillOnce(Return(2));
92    // And will call mount / and /dev.
93    EXPECT_CALL(mock, mount(_, _, _, _, _))
94      .WillOnce(Return(0))
95      .WillOnce(Return(0));
96
97    ki_init(&mock);
98  }
99
100  ~KernelWrapTest() {
101    ki_uninit();
102  }
103
104  KernelProxyMock mock;
105};
106
107}  // namespace
108
109
110TEST_F(KernelWrapTest, access) {
111  EXPECT_CALL(mock, access(StrEq("access"), 12)).Times(1);
112  access("access", 12);
113}
114
115TEST_F(KernelWrapTest, chdir) {
116  EXPECT_CALL(mock, chdir(StrEq("chdir"))).Times(1);
117  chdir("chdir");
118}
119
120TEST_F(KernelWrapTest, chmod) {
121  EXPECT_CALL(mock, chmod(StrEq("chmod"), 23)).Times(1);
122  chmod("chmod", 23);
123}
124
125TEST_F(KernelWrapTest, chown) {
126  uid_t uid = kDummyUid;
127  gid_t gid = kDummyGid;
128  EXPECT_CALL(mock, chown(StrEq("chown"), uid, gid)).Times(1);
129  chown("chown", uid, gid);
130}
131
132TEST_F(KernelWrapTest, close) {
133  EXPECT_CALL(mock, close(34)).Times(1);
134  close(34);
135}
136
137TEST_F(KernelWrapTest, dup) {
138  EXPECT_CALL(mock, dup(DUMMY_FD)).Times(1);
139  dup(DUMMY_FD);
140}
141
142TEST_F(KernelWrapTest, dup2) {
143  EXPECT_CALL(mock, dup2(DUMMY_FD, 234)).Times(1);
144  dup2(DUMMY_FD, 234);
145}
146
147TEST_F(KernelWrapTest, fchown) {
148  uid_t uid = kDummyUid;
149  gid_t gid = kDummyGid;
150  EXPECT_CALL(mock, fchown(DUMMY_FD, uid, gid)).Times(1);
151  fchown(DUMMY_FD, uid, gid);
152}
153
154TEST_F(KernelWrapTest, fcntl) {
155  char buffer[] = "fcntl";
156  EXPECT_CALL(mock, fcntl(012, 345, StrEq("fcntl"))).Times(1);
157  fcntl(012, 345, buffer);
158}
159
160TEST_F(KernelWrapTest, fstat) {
161  struct stat in_statbuf;
162  MakeDummyStatbuf(&in_statbuf);
163  EXPECT_CALL(mock, fstat(DUMMY_FD, _))
164      .Times(1)
165      .WillOnce(SetStat(&in_statbuf));
166  struct stat out_statbuf;
167  fstat(DUMMY_FD, &out_statbuf);
168  EXPECT_THAT(&in_statbuf, IsEqualToStatbuf(&out_statbuf));
169}
170
171TEST_F(KernelWrapTest, ftruncate) {
172  EXPECT_CALL(mock, ftruncate(456, 0)).Times(1);
173  ftruncate(456, 0);
174}
175
176TEST_F(KernelWrapTest, fsync) {
177  EXPECT_CALL(mock, fsync(345)).Times(1);
178  fsync(345);
179}
180
181TEST_F(KernelWrapTest, getcwd) {
182  EXPECT_CALL(mock, getcwd(StrEq("getcwd"), 1)).Times(1);
183  char buffer[] = "getcwd";
184  getcwd(buffer, 1);
185}
186
187TEST_F(KernelWrapTest, getdents) {
188#ifndef __GLIBC__
189  // TODO(sbc): Find a way to test the getdents wrapper under glibc.
190  // It looks like the only way to excerside it is to call readdir(2).
191  // There is an internal glibc function __getdents that will call the
192  // IRT but that cannot be accessed from here as glibc does not export it.
193  EXPECT_CALL(mock, getdents(456, NULL, 567)).WillOnce(Return(678));
194  EXPECT_EQ(getdents(456, NULL, 567), 678);
195#endif
196}
197
198// gcc gives error: getwd is deprecated.
199#if defined(__GNUC__)
200#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
201#endif
202TEST_F(KernelWrapTest, getwd) {
203  EXPECT_CALL(mock, getwd(StrEq("getwd"))).Times(1);
204  char buffer[] = "getwd";
205  getwd(buffer);
206}
207#if defined(__GNUC__)
208#pragma GCC diagnostic warning "-Wdeprecated-declarations"
209#endif
210
211TEST_F(KernelWrapTest, ioctl) {
212  char buffer[] = "ioctl";
213  EXPECT_CALL(mock, ioctl(012, 345, StrEq("ioctl"))).Times(1);
214  ioctl(012, 345, buffer);
215}
216
217TEST_F(KernelWrapTest, isatty) {
218  EXPECT_CALL(mock, isatty(678)).Times(1);
219  isatty(678);
220}
221
222TEST_F(KernelWrapTest, kill) {
223  EXPECT_CALL(mock, kill(22, 33)).Times(1);
224  kill(22, 33);
225}
226
227TEST_F(KernelWrapTest, lchown) {
228  uid_t uid = kDummyUid;
229  gid_t gid = kDummyGid;
230  EXPECT_CALL(mock, lchown(StrEq("lchown"), uid, gid)).Times(1);
231  lchown("lchown", uid, gid);
232}
233
234TEST_F(KernelWrapTest, lseek) {
235  EXPECT_CALL(mock, lseek(789, 891, 912)).Times(1);
236  lseek(789, 891, 912);
237}
238
239TEST_F(KernelWrapTest, mkdir) {
240#if defined(WIN32)
241  EXPECT_CALL(mock, mkdir(StrEq("mkdir"), 0777)).Times(1);
242  mkdir("mkdir");
243#else
244  EXPECT_CALL(mock, mkdir(StrEq("mkdir"), 1234)).Times(1);
245  mkdir("mkdir", 1234);
246#endif
247}
248
249TEST_F(KernelWrapTest, mount) {
250  EXPECT_CALL(mock,
251      mount(StrEq("mount1"), StrEq("mount2"), StrEq("mount3"), 2345, NULL))
252      .Times(1);
253  mount("mount1", "mount2", "mount3", 2345, NULL);
254}
255
256TEST_F(KernelWrapTest, open) {
257  EXPECT_CALL(mock, open(StrEq("open"), 3456)).Times(1);
258  open("open", 3456);
259}
260
261TEST_F(KernelWrapTest, pipe) {
262  int fds[2] = { 1, 2 };
263
264  EXPECT_CALL(mock, pipe(fds)).Times(1);
265  pipe(fds);
266}
267
268TEST_F(KernelWrapTest, read) {
269  EXPECT_CALL(mock, read(4567, NULL, 5678)).Times(1);
270  read(4567, NULL, 5678);
271}
272
273#ifdef __GLIBC__
274TEST_F(KernelWrapTest, remove) {
275  EXPECT_CALL(mock, remove(StrEq("remove"))).Times(1);
276  remove("remove");
277}
278#endif
279
280TEST_F(KernelWrapTest, rmdir) {
281  EXPECT_CALL(mock, rmdir(StrEq("rmdir"))).Times(1);
282  rmdir("rmdir");
283}
284
285static void handler(int) {
286}
287
288TEST_F(KernelWrapTest, sigset) {
289  EXPECT_CALL(mock, sigset(22, handler)).Times(1);
290  sigset(22, handler);
291}
292
293TEST_F(KernelWrapTest, signal) {
294  EXPECT_CALL(mock, sigset(22, handler)).Times(1);
295  signal(22, handler);
296}
297
298TEST_F(KernelWrapTest, stat) {
299  struct stat in_statbuf;
300  MakeDummyStatbuf(&in_statbuf);
301  EXPECT_CALL(mock, stat(StrEq("stat"), _))
302      .Times(1)
303      .WillOnce(SetStat(&in_statbuf));
304  struct stat out_statbuf;
305  stat("stat", &out_statbuf);
306  EXPECT_THAT(&in_statbuf, IsEqualToStatbuf(&out_statbuf));
307}
308
309TEST_F(KernelWrapTest, tcgetattr) {
310  struct termios term;
311  EXPECT_CALL(mock, tcgetattr(DUMMY_FD, &term)).Times(1);
312  tcgetattr(DUMMY_FD, &term);
313}
314
315TEST_F(KernelWrapTest, tcsetattr) {
316  struct termios term;
317  EXPECT_CALL(mock, tcsetattr(DUMMY_FD, 0, &term)).Times(1);
318  tcsetattr(DUMMY_FD, 0, &term);
319}
320
321TEST_F(KernelWrapTest, umount) {
322  EXPECT_CALL(mock, umount(StrEq("umount"))).Times(1);
323  umount("umount");
324}
325
326TEST_F(KernelWrapTest, unlink) {
327  EXPECT_CALL(mock, unlink(StrEq("unlink"))).Times(1);
328  unlink("unlink");
329}
330
331TEST_F(KernelWrapTest, utime) {
332  const struct utimbuf* times = NULL;
333  EXPECT_CALL(mock, utime(StrEq("utime"), times));
334  utime("utime", times);
335}
336
337TEST_F(KernelWrapTest, write) {
338  EXPECT_CALL(mock, write(6789, NULL, 7891)).Times(1);
339  write(6789, NULL, 7891);
340}
341
342#ifdef PROVIDES_SOCKET_API
343TEST_F(KernelWrapTest, poll) {
344  EXPECT_CALL(mock, poll(NULL, 5, -1));
345  poll(NULL, 5, -1);
346}
347
348TEST_F(KernelWrapTest, select) {
349  EXPECT_CALL(mock, select(123, NULL, NULL, NULL, NULL));
350  select(123, NULL, NULL, NULL, NULL);
351}
352
353// Socket Functions
354TEST_F(KernelWrapTest, accept) {
355  EXPECT_CALL(mock, accept(DUMMY_FD, NULL, NULL)).Times(1);
356  accept(DUMMY_FD, NULL, NULL);
357}
358
359TEST_F(KernelWrapTest, bind) {
360  EXPECT_CALL(mock, bind(DUMMY_FD, NULL, 456)).Times(1);
361  bind(DUMMY_FD, NULL, 456);
362}
363
364TEST_F(KernelWrapTest, connect) {
365  EXPECT_CALL(mock, connect(DUMMY_FD, NULL, 456)).Times(1);
366  connect(DUMMY_FD, NULL, 456);
367}
368
369TEST_F(KernelWrapTest, gethostbyname) {
370  EXPECT_CALL(mock, gethostbyname(NULL)).Times(1);
371  gethostbyname(NULL);
372}
373
374TEST_F(KernelWrapTest, getpeername) {
375  EXPECT_CALL(mock, getpeername(DUMMY_FD, NULL, NULL)).Times(1);
376  getpeername(DUMMY_FD, NULL, NULL);
377}
378
379TEST_F(KernelWrapTest, getsockname) {
380  EXPECT_CALL(mock, getsockname(DUMMY_FD, NULL, NULL)).Times(1);
381  getsockname(DUMMY_FD, NULL, NULL);
382}
383
384TEST_F(KernelWrapTest, getsockopt) {
385  EXPECT_CALL(mock, getsockopt(DUMMY_FD, 456, 789, NULL, NULL)).Times(1);
386  getsockopt(DUMMY_FD, 456, 789, NULL, NULL);
387}
388
389TEST_F(KernelWrapTest, listen) {
390  EXPECT_CALL(mock, listen(DUMMY_FD, 456)).Times(1);
391  listen(DUMMY_FD, 456);
392}
393
394TEST_F(KernelWrapTest, recv) {
395  EXPECT_CALL(mock, recv(DUMMY_FD, NULL, 456, 789)).Times(1);
396  recv(DUMMY_FD, NULL, 456, 789);
397}
398
399TEST_F(KernelWrapTest, recvfrom) {
400  EXPECT_CALL(mock, recvfrom(DUMMY_FD, NULL, 456, 789, NULL, NULL)).Times(1);
401  recvfrom(DUMMY_FD, NULL, 456, 789, NULL, NULL);
402}
403
404TEST_F(KernelWrapTest, recvmsg) {
405  EXPECT_CALL(mock, recvmsg(DUMMY_FD, NULL, 456)).Times(1);
406  recvmsg(DUMMY_FD, NULL, 456);
407}
408
409TEST_F(KernelWrapTest, send) {
410  EXPECT_CALL(mock, send(DUMMY_FD, NULL, 456, 789)).Times(1);
411  send(DUMMY_FD, NULL, 456, 789);
412}
413
414TEST_F(KernelWrapTest, sendto) {
415  EXPECT_CALL(mock, sendto(DUMMY_FD, NULL, 456, 789, NULL, 314)).Times(1);
416  sendto(DUMMY_FD, NULL, 456, 789, NULL, 314);
417}
418
419TEST_F(KernelWrapTest, sendmsg) {
420  EXPECT_CALL(mock, sendmsg(DUMMY_FD, NULL, 456)).Times(1);
421  sendmsg(DUMMY_FD, NULL, 456);
422}
423
424TEST_F(KernelWrapTest, setsockopt) {
425  EXPECT_CALL(mock, setsockopt(DUMMY_FD, 456, 789, NULL, 314)).Times(1);
426  setsockopt(DUMMY_FD, 456, 789, NULL, 314);
427}
428
429TEST_F(KernelWrapTest, shutdown) {
430  EXPECT_CALL(mock, shutdown(DUMMY_FD, 456)).Times(1);
431  shutdown(DUMMY_FD, 456);
432}
433
434TEST_F(KernelWrapTest, socket) {
435  EXPECT_CALL(mock, socket(DUMMY_FD, 456, 789)).Times(1);
436  socket(DUMMY_FD, 456, 789);
437}
438
439TEST_F(KernelWrapTest, socketpair) {
440  EXPECT_CALL(mock, socketpair(DUMMY_FD, 456, 789, NULL)).Times(1);
441  socketpair(DUMMY_FD, 456, 789, NULL);
442}
443
444#endif // PROVIDES_SOCKET_API
445