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/ipc_message_attachment_set.h"
8
9 #include <fcntl.h>
10 #include <stddef.h>
11 #include <unistd.h>
12
13 #include "base/posix/eintr_wrapper.h"
14 #include "build/build_config.h"
15 #include "ipc/ipc_platform_file_attachment_posix.h"
16 #include "testing/gtest/include/gtest/gtest.h"
17
18 namespace IPC {
19 namespace {
20
21 // Get a safe file descriptor for test purposes.
GetSafeFd()22 int GetSafeFd() {
23 return open("/dev/null", O_RDONLY);
24 }
25
26 // Returns true if fd was already closed. Closes fd if not closed.
VerifyClosed(int fd)27 bool VerifyClosed(int fd) {
28 const int duped = HANDLE_EINTR(dup(fd));
29 if (duped != -1) {
30 EXPECT_NE(IGNORE_EINTR(close(duped)), -1);
31 EXPECT_NE(IGNORE_EINTR(close(fd)), -1);
32 return false;
33 }
34 return true;
35 }
36
GetFdAt(MessageAttachmentSet * set,int id)37 int GetFdAt(MessageAttachmentSet* set, int id) {
38 return static_cast<internal::PlatformFileAttachment&>(
39 *set->GetAttachmentAt(id))
40 .TakePlatformFile();
41 }
42
43 // The MessageAttachmentSet will try and close some of the descriptor numbers
44 // which we given it. This is the base descriptor value. It's great enough such
45 // that no real descriptor will accidently be closed.
46 static const int kFDBase = 50000;
47
TEST(MessageAttachmentSet,BasicAdd)48 TEST(MessageAttachmentSet, BasicAdd) {
49 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
50
51 ASSERT_EQ(set->size(), 0u);
52 ASSERT_TRUE(set->empty());
53 ASSERT_TRUE(
54 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase)));
55 ASSERT_EQ(set->size(), 1u);
56 ASSERT_TRUE(!set->empty());
57
58 // Empties the set and stops a warning about deleting a set with unconsumed
59 // descriptors
60 set->CommitAllDescriptors();
61 }
62
TEST(MessageAttachmentSet,BasicAddAndClose)63 TEST(MessageAttachmentSet, BasicAddAndClose) {
64 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
65
66 ASSERT_EQ(set->size(), 0u);
67 ASSERT_TRUE(set->empty());
68 const int fd = GetSafeFd();
69 ASSERT_TRUE(set->AddAttachment(
70 new internal::PlatformFileAttachment(base::ScopedFD(fd))));
71 ASSERT_EQ(set->size(), 1u);
72 ASSERT_TRUE(!set->empty());
73
74 set->CommitAllDescriptors();
75
76 ASSERT_TRUE(VerifyClosed(fd));
77 }
TEST(MessageAttachmentSet,MaxSize)78 TEST(MessageAttachmentSet, MaxSize) {
79 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
80
81 for (size_t i = 0; i < MessageAttachmentSet::kMaxDescriptorsPerMessage; ++i)
82 ASSERT_TRUE(set->AddAttachment(
83 new internal::PlatformFileAttachment(kFDBase + 1 + i)));
84
85 ASSERT_TRUE(
86 !set->AddAttachment(new internal::PlatformFileAttachment(kFDBase)));
87
88 set->CommitAllDescriptors();
89 }
90
TEST(MessageAttachmentSet,WalkInOrder)91 TEST(MessageAttachmentSet, WalkInOrder) {
92 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
93
94 ASSERT_TRUE(
95 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase)));
96 ASSERT_TRUE(
97 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase + 1)));
98 ASSERT_TRUE(
99 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase + 2)));
100
101 ASSERT_EQ(GetFdAt(set.get(), 0), kFDBase);
102 ASSERT_EQ(GetFdAt(set.get(), 1), kFDBase + 1);
103 ASSERT_EQ(GetFdAt(set.get(), 2), kFDBase + 2);
104 ASSERT_FALSE(set->GetAttachmentAt(0));
105
106 set->CommitAllDescriptors();
107 }
108
TEST(MessageAttachmentSet,WalkWrongOrder)109 TEST(MessageAttachmentSet, WalkWrongOrder) {
110 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
111
112 ASSERT_TRUE(
113 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase)));
114 ASSERT_TRUE(
115 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase + 1)));
116 ASSERT_TRUE(
117 set->AddAttachment(new internal::PlatformFileAttachment(kFDBase + 2)));
118
119 ASSERT_EQ(GetFdAt(set.get(), 0), kFDBase);
120 ASSERT_FALSE(set->GetAttachmentAt(2));
121
122 set->CommitAllDescriptors();
123 }
124
125 #if defined(OS_ANDROID)
126 #define MAYBE_DontClose DISABLED_DontClose
127 #else
128 #define MAYBE_DontClose DontClose
129 #endif
TEST(MessageAttachmentSet,MAYBE_DontClose)130 TEST(MessageAttachmentSet, MAYBE_DontClose) {
131 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
132
133 const int fd = GetSafeFd();
134 ASSERT_TRUE(set->AddAttachment(new internal::PlatformFileAttachment(fd)));
135 set->CommitAllDescriptors();
136
137 ASSERT_FALSE(VerifyClosed(fd));
138 }
139
TEST(MessageAttachmentSet,DoClose)140 TEST(MessageAttachmentSet, DoClose) {
141 scoped_refptr<MessageAttachmentSet> set(new MessageAttachmentSet);
142
143 const int fd = GetSafeFd();
144 ASSERT_TRUE(set->AddAttachment(
145 new internal::PlatformFileAttachment(base::ScopedFD(fd))));
146 set->CommitAllDescriptors();
147
148 ASSERT_TRUE(VerifyClosed(fd));
149 }
150
151 } // namespace
152 } // namespace IPC
153