1 // Copyright (c) 2012 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.
5 #include "base/posix/file_descriptor_shuffle.h"
6 #include "testing/gtest/include/gtest/gtest.h"
10 // 'Duplicated' file descriptors start at this number
11 const int kDuplicateBase
= 1000;
24 Action(Type in_type
, int in_fd1
, int in_fd2
= -1)
30 bool operator==(const Action
& other
) const {
31 return other
.type
== type
&&
41 class InjectionTracer
: public InjectionDelegate
{
44 : next_duplicate_(kDuplicateBase
) {
47 bool Duplicate(int* result
, int fd
) override
{
48 *result
= next_duplicate_
++;
49 actions_
.push_back(Action(Action::DUPLICATE
, *result
, fd
));
53 bool Move(int src
, int dest
) override
{
54 actions_
.push_back(Action(Action::MOVE
, src
, dest
));
58 void Close(int fd
) override
{ actions_
.push_back(Action(Action::CLOSE
, fd
)); }
60 const std::vector
<Action
>& actions() const { return actions_
; }
64 std::vector
<Action
> actions_
;
67 TEST(FileDescriptorShuffleTest
, Empty
) {
68 InjectiveMultimap map
;
69 InjectionTracer tracer
;
71 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
72 EXPECT_EQ(0u, tracer
.actions().size());
75 TEST(FileDescriptorShuffleTest
, Noop
) {
76 InjectiveMultimap map
;
77 InjectionTracer tracer
;
78 map
.push_back(InjectionArc(0, 0, false));
80 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
81 EXPECT_EQ(0u, tracer
.actions().size());
84 TEST(FileDescriptorShuffleTest
, NoopAndClose
) {
85 InjectiveMultimap map
;
86 InjectionTracer tracer
;
87 map
.push_back(InjectionArc(0, 0, true));
89 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
90 EXPECT_EQ(0u, tracer
.actions().size());
93 TEST(FileDescriptorShuffleTest
, Simple1
) {
94 InjectiveMultimap map
;
95 InjectionTracer tracer
;
96 map
.push_back(InjectionArc(0, 1, false));
98 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
99 ASSERT_EQ(1u, tracer
.actions().size());
100 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
103 TEST(FileDescriptorShuffleTest
, Simple2
) {
104 InjectiveMultimap map
;
105 InjectionTracer tracer
;
106 map
.push_back(InjectionArc(0, 1, false));
107 map
.push_back(InjectionArc(2, 3, false));
109 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
110 ASSERT_EQ(2u, tracer
.actions().size());
111 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
112 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 2, 3));
115 TEST(FileDescriptorShuffleTest
, Simple3
) {
116 InjectiveMultimap map
;
117 InjectionTracer tracer
;
118 map
.push_back(InjectionArc(0, 1, true));
120 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
121 ASSERT_EQ(2u, tracer
.actions().size());
122 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
123 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::CLOSE
, 0));
126 TEST(FileDescriptorShuffleTest
, Simple4
) {
127 InjectiveMultimap map
;
128 InjectionTracer tracer
;
129 map
.push_back(InjectionArc(10, 0, true));
130 map
.push_back(InjectionArc(1, 1, true));
132 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
133 ASSERT_EQ(2u, tracer
.actions().size());
134 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 10, 0));
135 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::CLOSE
, 10));
138 TEST(FileDescriptorShuffleTest
, Cycle
) {
139 InjectiveMultimap map
;
140 InjectionTracer tracer
;
141 map
.push_back(InjectionArc(0, 1, false));
142 map
.push_back(InjectionArc(1, 0, false));
144 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
145 ASSERT_EQ(4u, tracer
.actions().size());
146 EXPECT_TRUE(tracer
.actions()[0] ==
147 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
148 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
149 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
150 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
153 TEST(FileDescriptorShuffleTest
, CycleAndClose1
) {
154 InjectiveMultimap map
;
155 InjectionTracer tracer
;
156 map
.push_back(InjectionArc(0, 1, true));
157 map
.push_back(InjectionArc(1, 0, false));
159 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
160 ASSERT_EQ(4u, tracer
.actions().size());
161 EXPECT_TRUE(tracer
.actions()[0] ==
162 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
163 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
164 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
165 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
168 TEST(FileDescriptorShuffleTest
, CycleAndClose2
) {
169 InjectiveMultimap map
;
170 InjectionTracer tracer
;
171 map
.push_back(InjectionArc(0, 1, false));
172 map
.push_back(InjectionArc(1, 0, true));
174 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
175 ASSERT_EQ(4u, tracer
.actions().size());
176 EXPECT_TRUE(tracer
.actions()[0] ==
177 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
178 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
179 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
180 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
183 TEST(FileDescriptorShuffleTest
, CycleAndClose3
) {
184 InjectiveMultimap map
;
185 InjectionTracer tracer
;
186 map
.push_back(InjectionArc(0, 1, true));
187 map
.push_back(InjectionArc(1, 0, true));
189 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
190 ASSERT_EQ(4u, tracer
.actions().size());
191 EXPECT_TRUE(tracer
.actions()[0] ==
192 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
193 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
194 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
195 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
198 TEST(FileDescriptorShuffleTest
, Fanout
) {
199 InjectiveMultimap map
;
200 InjectionTracer tracer
;
201 map
.push_back(InjectionArc(0, 1, false));
202 map
.push_back(InjectionArc(0, 2, false));
204 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
205 ASSERT_EQ(2u, tracer
.actions().size());
206 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
207 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
210 TEST(FileDescriptorShuffleTest
, FanoutAndClose1
) {
211 InjectiveMultimap map
;
212 InjectionTracer tracer
;
213 map
.push_back(InjectionArc(0, 1, true));
214 map
.push_back(InjectionArc(0, 2, false));
216 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
217 ASSERT_EQ(3u, tracer
.actions().size());
218 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
219 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
220 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::CLOSE
, 0));
223 TEST(FileDescriptorShuffleTest
, FanoutAndClose2
) {
224 InjectiveMultimap map
;
225 InjectionTracer tracer
;
226 map
.push_back(InjectionArc(0, 1, false));
227 map
.push_back(InjectionArc(0, 2, true));
229 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
230 ASSERT_EQ(3u, tracer
.actions().size());
231 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
232 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
233 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::CLOSE
, 0));
236 TEST(FileDescriptorShuffleTest
, FanoutAndClose3
) {
237 InjectiveMultimap map
;
238 InjectionTracer tracer
;
239 map
.push_back(InjectionArc(0, 1, true));
240 map
.push_back(InjectionArc(0, 2, true));
242 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
243 ASSERT_EQ(3u, tracer
.actions().size());
244 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
245 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
246 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::CLOSE
, 0));
249 class FailingDelegate
: public InjectionDelegate
{
251 bool Duplicate(int* result
, int fd
) override
{ return false; }
253 bool Move(int src
, int dest
) override
{ return false; }
255 void Close(int fd
) override
{}
258 TEST(FileDescriptorShuffleTest
, EmptyWithFailure
) {
259 InjectiveMultimap map
;
260 FailingDelegate failing
;
262 EXPECT_TRUE(PerformInjectiveMultimap(map
, &failing
));
265 TEST(FileDescriptorShuffleTest
, NoopWithFailure
) {
266 InjectiveMultimap map
;
267 FailingDelegate failing
;
268 map
.push_back(InjectionArc(0, 0, false));
270 EXPECT_TRUE(PerformInjectiveMultimap(map
, &failing
));
273 TEST(FileDescriptorShuffleTest
, Simple1WithFailure
) {
274 InjectiveMultimap map
;
275 FailingDelegate failing
;
276 map
.push_back(InjectionArc(0, 1, false));
278 EXPECT_FALSE(PerformInjectiveMultimap(map
, &failing
));