Home | History | Annotate | Download | only in ipc
      1 // Copyright (c) 2011 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 // This test is POSIX only.
      6 
      7 #include "ipc/file_descriptor_set_posix.h"
      8 
      9 #include <unistd.h>
     10 #include <fcntl.h>
     11 
     12 #include "base/basictypes.h"
     13 #include "base/posix/eintr_wrapper.h"
     14 #include "testing/gtest/include/gtest/gtest.h"
     15 
     16 namespace {
     17 
     18 // Get a safe file descriptor for test purposes.
     19 int GetSafeFd() {
     20   return open("/dev/null", O_RDONLY);
     21 }
     22 
     23 // Returns true if fd was already closed.  Closes fd if not closed.
     24 bool VerifyClosed(int fd) {
     25   const int duped = dup(fd);
     26   if (duped != -1) {
     27     EXPECT_NE(IGNORE_EINTR(close(duped)), -1);
     28     EXPECT_NE(IGNORE_EINTR(close(fd)), -1);
     29     return false;
     30   }
     31   return true;
     32 }
     33 
     34 // The FileDescriptorSet will try and close some of the descriptor numbers
     35 // which we given it. This is the base descriptor value. It's great enough such
     36 // that no real descriptor will accidently be closed.
     37 static const int kFDBase = 50000;
     38 
     39 TEST(FileDescriptorSet, BasicAdd) {
     40   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
     41 
     42   ASSERT_EQ(set->size(), 0u);
     43   ASSERT_TRUE(set->empty());
     44   ASSERT_TRUE(set->AddToBorrow(kFDBase));
     45   ASSERT_EQ(set->size(), 1u);
     46   ASSERT_TRUE(!set->empty());
     47 
     48   // Empties the set and stops a warning about deleting a set with unconsumed
     49   // descriptors
     50   set->CommitAll();
     51 }
     52 
     53 TEST(FileDescriptorSet, BasicAddAndClose) {
     54   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
     55 
     56   ASSERT_EQ(set->size(), 0u);
     57   ASSERT_TRUE(set->empty());
     58   const int fd = GetSafeFd();
     59   ASSERT_TRUE(set->AddToOwn(base::ScopedFD(fd)));
     60   ASSERT_EQ(set->size(), 1u);
     61   ASSERT_TRUE(!set->empty());
     62 
     63   set->CommitAll();
     64 
     65   ASSERT_TRUE(VerifyClosed(fd));
     66 }
     67 TEST(FileDescriptorSet, MaxSize) {
     68   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
     69 
     70   for (size_t i = 0; i < FileDescriptorSet::kMaxDescriptorsPerMessage; ++i)
     71     ASSERT_TRUE(set->AddToBorrow(kFDBase + 1 + i));
     72 
     73   ASSERT_TRUE(!set->AddToBorrow(kFDBase));
     74 
     75   set->CommitAll();
     76 }
     77 
     78 TEST(FileDescriptorSet, SetDescriptors) {
     79   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
     80 
     81   ASSERT_TRUE(set->empty());
     82   set->AddDescriptorsToOwn(NULL, 0);
     83   ASSERT_TRUE(set->empty());
     84 
     85   const int fd = GetSafeFd();
     86   static const int fds[] = {fd};
     87   set->AddDescriptorsToOwn(fds, 1);
     88   ASSERT_TRUE(!set->empty());
     89   ASSERT_EQ(set->size(), 1u);
     90 
     91   set->CommitAll();
     92 
     93   ASSERT_TRUE(VerifyClosed(fd));
     94 }
     95 
     96 TEST(FileDescriptorSet, PeekDescriptors) {
     97   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
     98 
     99   set->PeekDescriptors(NULL);
    100   ASSERT_TRUE(set->AddToBorrow(kFDBase));
    101 
    102   int fds[1];
    103   fds[0] = 0;
    104   set->PeekDescriptors(fds);
    105   ASSERT_EQ(fds[0], kFDBase);
    106   set->CommitAll();
    107   ASSERT_TRUE(set->empty());
    108 }
    109 
    110 TEST(FileDescriptorSet, WalkInOrder) {
    111   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
    112 
    113   // TODO(morrita): This test is wrong. TakeDescriptorAt() shouldn't be
    114   // used to retrieve borrowed descriptors. That never happens in production.
    115   ASSERT_TRUE(set->AddToBorrow(kFDBase));
    116   ASSERT_TRUE(set->AddToBorrow(kFDBase + 1));
    117   ASSERT_TRUE(set->AddToBorrow(kFDBase + 2));
    118 
    119   ASSERT_EQ(set->TakeDescriptorAt(0), kFDBase);
    120   ASSERT_EQ(set->TakeDescriptorAt(1), kFDBase + 1);
    121   ASSERT_EQ(set->TakeDescriptorAt(2), kFDBase + 2);
    122 
    123   set->CommitAll();
    124 }
    125 
    126 TEST(FileDescriptorSet, WalkWrongOrder) {
    127   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
    128 
    129   // TODO(morrita): This test is wrong. TakeDescriptorAt() shouldn't be
    130   // used to retrieve borrowed descriptors. That never happens in production.
    131   ASSERT_TRUE(set->AddToBorrow(kFDBase));
    132   ASSERT_TRUE(set->AddToBorrow(kFDBase + 1));
    133   ASSERT_TRUE(set->AddToBorrow(kFDBase + 2));
    134 
    135   ASSERT_EQ(set->TakeDescriptorAt(0), kFDBase);
    136   ASSERT_EQ(set->TakeDescriptorAt(2), -1);
    137 
    138   set->CommitAll();
    139 }
    140 
    141 TEST(FileDescriptorSet, WalkCycle) {
    142   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
    143 
    144   // TODO(morrita): This test is wrong. TakeDescriptorAt() shouldn't be
    145   // used to retrieve borrowed descriptors. That never happens in production.
    146   ASSERT_TRUE(set->AddToBorrow(kFDBase));
    147   ASSERT_TRUE(set->AddToBorrow(kFDBase + 1));
    148   ASSERT_TRUE(set->AddToBorrow(kFDBase + 2));
    149 
    150   ASSERT_EQ(set->TakeDescriptorAt(0), kFDBase);
    151   ASSERT_EQ(set->TakeDescriptorAt(1), kFDBase + 1);
    152   ASSERT_EQ(set->TakeDescriptorAt(2), kFDBase + 2);
    153   ASSERT_EQ(set->TakeDescriptorAt(0), kFDBase);
    154   ASSERT_EQ(set->TakeDescriptorAt(1), kFDBase + 1);
    155   ASSERT_EQ(set->TakeDescriptorAt(2), kFDBase + 2);
    156   ASSERT_EQ(set->TakeDescriptorAt(0), kFDBase);
    157   ASSERT_EQ(set->TakeDescriptorAt(1), kFDBase + 1);
    158   ASSERT_EQ(set->TakeDescriptorAt(2), kFDBase + 2);
    159 
    160   set->CommitAll();
    161 }
    162 
    163 TEST(FileDescriptorSet, DontClose) {
    164   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
    165 
    166   const int fd = GetSafeFd();
    167   ASSERT_TRUE(set->AddToBorrow(fd));
    168   set->CommitAll();
    169 
    170   ASSERT_FALSE(VerifyClosed(fd));
    171 }
    172 
    173 TEST(FileDescriptorSet, DoClose) {
    174   scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet);
    175 
    176   const int fd = GetSafeFd();
    177   ASSERT_TRUE(set->AddToOwn(base::ScopedFD(fd)));
    178   set->CommitAll();
    179 
    180   ASSERT_TRUE(VerifyClosed(fd));
    181 }
    182 
    183 }  // namespace
    184