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 16namespace { 17 18// Get a safe file descriptor for test purposes. 19int GetSafeFd() { 20 return open("/dev/null", O_RDONLY); 21} 22 23// Returns true if fd was already closed. Closes fd if not closed. 24bool 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. 37static const int kFDBase = 50000; 38 39TEST(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 53TEST(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} 67TEST(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 78TEST(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 96TEST(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 110TEST(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 126TEST(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 141TEST(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 163TEST(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 173TEST(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