blob: b4a01414a551513bb06b3e4bdaf85cc8b83622e0 [file] [log] [blame]
// 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