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