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