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