| // Copyright (c) 2011 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // This test is POSIX only. |
| |
| #include "ipc/file_descriptor_set_posix.h" |
| |
| #include <unistd.h> |
| #include <fcntl.h> |
| |
| #include "base/basictypes.h" |
| #include "base/posix/eintr_wrapper.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| |
| namespace { |
| |
| // Get a safe file descriptor for test purposes. |
| int GetSafeFd() { |
| return open("/dev/null", O_RDONLY); |
| } |
| |
| // Returns true if fd was already closed. Closes fd if not closed. |
| bool VerifyClosed(int fd) { |
| const int duped = dup(fd); |
| if (duped != -1) { |
| EXPECT_NE(HANDLE_EINTR(close(duped)), -1); |
| EXPECT_NE(HANDLE_EINTR(close(fd)), -1); |
| return false; |
| } |
| return true; |
| } |
| |
| // The FileDescriptorSet will try and close some of the descriptor numbers |
| // which we given it. This is the base descriptor value. It's great enough such |
| // that no real descriptor will accidently be closed. |
| static const int kFDBase = 50000; |
| |
| TEST(FileDescriptorSet, BasicAdd) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| ASSERT_EQ(set->size(), 0u); |
| ASSERT_TRUE(set->empty()); |
| ASSERT_TRUE(set->Add(kFDBase)); |
| ASSERT_EQ(set->size(), 1u); |
| ASSERT_TRUE(!set->empty()); |
| |
| // Empties the set and stops a warning about deleting a set with unconsumed |
| // descriptors |
| set->CommitAll(); |
| } |
| |
| TEST(FileDescriptorSet, BasicAddAndClose) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| ASSERT_EQ(set->size(), 0u); |
| ASSERT_TRUE(set->empty()); |
| const int fd = GetSafeFd(); |
| ASSERT_TRUE(set->AddAndAutoClose(fd)); |
| ASSERT_EQ(set->size(), 1u); |
| ASSERT_TRUE(!set->empty()); |
| |
| set->CommitAll(); |
| |
| ASSERT_TRUE(VerifyClosed(fd)); |
| } |
| TEST(FileDescriptorSet, MaxSize) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| for (size_t i = 0; i < FileDescriptorSet::kMaxDescriptorsPerMessage; ++i) |
| ASSERT_TRUE(set->Add(kFDBase + 1 + i)); |
| |
| ASSERT_TRUE(!set->Add(kFDBase)); |
| |
| set->CommitAll(); |
| } |
| |
| TEST(FileDescriptorSet, SetDescriptors) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| ASSERT_TRUE(set->empty()); |
| set->SetDescriptors(NULL, 0); |
| ASSERT_TRUE(set->empty()); |
| |
| const int fd = GetSafeFd(); |
| static const int fds[] = {fd}; |
| set->SetDescriptors(fds, 1); |
| ASSERT_TRUE(!set->empty()); |
| ASSERT_EQ(set->size(), 1u); |
| |
| set->CommitAll(); |
| |
| ASSERT_TRUE(VerifyClosed(fd)); |
| } |
| |
| TEST(FileDescriptorSet, GetDescriptors) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| set->GetDescriptors(NULL); |
| ASSERT_TRUE(set->Add(kFDBase)); |
| |
| int fds[1]; |
| fds[0] = 0; |
| set->GetDescriptors(fds); |
| ASSERT_EQ(fds[0], kFDBase); |
| set->CommitAll(); |
| ASSERT_TRUE(set->empty()); |
| } |
| |
| TEST(FileDescriptorSet, WalkInOrder) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| ASSERT_TRUE(set->Add(kFDBase)); |
| ASSERT_TRUE(set->Add(kFDBase + 1)); |
| ASSERT_TRUE(set->Add(kFDBase + 2)); |
| |
| ASSERT_EQ(set->GetDescriptorAt(0), kFDBase); |
| ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1); |
| ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2); |
| |
| set->CommitAll(); |
| } |
| |
| TEST(FileDescriptorSet, WalkWrongOrder) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| ASSERT_TRUE(set->Add(kFDBase)); |
| ASSERT_TRUE(set->Add(kFDBase + 1)); |
| ASSERT_TRUE(set->Add(kFDBase + 2)); |
| |
| ASSERT_EQ(set->GetDescriptorAt(0), kFDBase); |
| ASSERT_EQ(set->GetDescriptorAt(2), -1); |
| |
| set->CommitAll(); |
| } |
| |
| TEST(FileDescriptorSet, WalkCycle) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| ASSERT_TRUE(set->Add(kFDBase)); |
| ASSERT_TRUE(set->Add(kFDBase + 1)); |
| ASSERT_TRUE(set->Add(kFDBase + 2)); |
| |
| ASSERT_EQ(set->GetDescriptorAt(0), kFDBase); |
| ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1); |
| ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2); |
| ASSERT_EQ(set->GetDescriptorAt(0), kFDBase); |
| ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1); |
| ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2); |
| ASSERT_EQ(set->GetDescriptorAt(0), kFDBase); |
| ASSERT_EQ(set->GetDescriptorAt(1), kFDBase + 1); |
| ASSERT_EQ(set->GetDescriptorAt(2), kFDBase + 2); |
| |
| set->CommitAll(); |
| } |
| |
| TEST(FileDescriptorSet, DontClose) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| const int fd = GetSafeFd(); |
| ASSERT_TRUE(set->Add(fd)); |
| set->CommitAll(); |
| |
| ASSERT_FALSE(VerifyClosed(fd)); |
| } |
| |
| TEST(FileDescriptorSet, DoClose) { |
| scoped_refptr<FileDescriptorSet> set(new FileDescriptorSet); |
| |
| const int fd = GetSafeFd(); |
| ASSERT_TRUE(set->AddAndAutoClose(fd)); |
| set->CommitAll(); |
| |
| ASSERT_TRUE(VerifyClosed(fd)); |
| } |
| |
| } // namespace |