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 virtual bool Duplicate(int* result
, int fd
) OVERRIDE
{
48 *result
= next_duplicate_
++;
49 actions_
.push_back(Action(Action::DUPLICATE
, *result
, fd
));
53 virtual bool Move(int src
, int dest
) OVERRIDE
{
54 actions_
.push_back(Action(Action::MOVE
, src
, dest
));
58 virtual void Close(int fd
) OVERRIDE
{
59 actions_
.push_back(Action(Action::CLOSE
, fd
));
62 const std::vector
<Action
>& actions() const { return actions_
; }
66 std::vector
<Action
> actions_
;
69 TEST(FileDescriptorShuffleTest
, Empty
) {
70 InjectiveMultimap map
;
71 InjectionTracer tracer
;
73 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
74 EXPECT_EQ(0u, tracer
.actions().size());
77 TEST(FileDescriptorShuffleTest
, Noop
) {
78 InjectiveMultimap map
;
79 InjectionTracer tracer
;
80 map
.push_back(InjectionArc(0, 0, false));
82 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
83 EXPECT_EQ(0u, tracer
.actions().size());
86 TEST(FileDescriptorShuffleTest
, NoopAndClose
) {
87 InjectiveMultimap map
;
88 InjectionTracer tracer
;
89 map
.push_back(InjectionArc(0, 0, true));
91 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
92 EXPECT_EQ(0u, tracer
.actions().size());
95 TEST(FileDescriptorShuffleTest
, Simple1
) {
96 InjectiveMultimap map
;
97 InjectionTracer tracer
;
98 map
.push_back(InjectionArc(0, 1, false));
100 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
101 ASSERT_EQ(1u, tracer
.actions().size());
102 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
105 TEST(FileDescriptorShuffleTest
, Simple2
) {
106 InjectiveMultimap map
;
107 InjectionTracer tracer
;
108 map
.push_back(InjectionArc(0, 1, false));
109 map
.push_back(InjectionArc(2, 3, false));
111 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
112 ASSERT_EQ(2u, tracer
.actions().size());
113 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
114 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 2, 3));
117 TEST(FileDescriptorShuffleTest
, Simple3
) {
118 InjectiveMultimap map
;
119 InjectionTracer tracer
;
120 map
.push_back(InjectionArc(0, 1, true));
122 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
123 ASSERT_EQ(2u, tracer
.actions().size());
124 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
125 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::CLOSE
, 0));
128 TEST(FileDescriptorShuffleTest
, Simple4
) {
129 InjectiveMultimap map
;
130 InjectionTracer tracer
;
131 map
.push_back(InjectionArc(10, 0, true));
132 map
.push_back(InjectionArc(1, 1, true));
134 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
135 ASSERT_EQ(2u, tracer
.actions().size());
136 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 10, 0));
137 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::CLOSE
, 10));
140 TEST(FileDescriptorShuffleTest
, Cycle
) {
141 InjectiveMultimap map
;
142 InjectionTracer tracer
;
143 map
.push_back(InjectionArc(0, 1, false));
144 map
.push_back(InjectionArc(1, 0, false));
146 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
147 ASSERT_EQ(4u, tracer
.actions().size());
148 EXPECT_TRUE(tracer
.actions()[0] ==
149 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
150 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
151 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
152 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
155 TEST(FileDescriptorShuffleTest
, CycleAndClose1
) {
156 InjectiveMultimap map
;
157 InjectionTracer tracer
;
158 map
.push_back(InjectionArc(0, 1, true));
159 map
.push_back(InjectionArc(1, 0, false));
161 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
162 ASSERT_EQ(4u, tracer
.actions().size());
163 EXPECT_TRUE(tracer
.actions()[0] ==
164 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
165 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
166 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
167 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
170 TEST(FileDescriptorShuffleTest
, CycleAndClose2
) {
171 InjectiveMultimap map
;
172 InjectionTracer tracer
;
173 map
.push_back(InjectionArc(0, 1, false));
174 map
.push_back(InjectionArc(1, 0, true));
176 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
177 ASSERT_EQ(4u, tracer
.actions().size());
178 EXPECT_TRUE(tracer
.actions()[0] ==
179 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
180 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
181 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
182 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
185 TEST(FileDescriptorShuffleTest
, CycleAndClose3
) {
186 InjectiveMultimap map
;
187 InjectionTracer tracer
;
188 map
.push_back(InjectionArc(0, 1, true));
189 map
.push_back(InjectionArc(1, 0, true));
191 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
192 ASSERT_EQ(4u, tracer
.actions().size());
193 EXPECT_TRUE(tracer
.actions()[0] ==
194 Action(Action::DUPLICATE
, kDuplicateBase
, 1));
195 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 1));
196 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::MOVE
, kDuplicateBase
, 0));
197 EXPECT_TRUE(tracer
.actions()[3] == Action(Action::CLOSE
, kDuplicateBase
));
200 TEST(FileDescriptorShuffleTest
, Fanout
) {
201 InjectiveMultimap map
;
202 InjectionTracer tracer
;
203 map
.push_back(InjectionArc(0, 1, false));
204 map
.push_back(InjectionArc(0, 2, false));
206 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
207 ASSERT_EQ(2u, tracer
.actions().size());
208 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
209 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
212 TEST(FileDescriptorShuffleTest
, FanoutAndClose1
) {
213 InjectiveMultimap map
;
214 InjectionTracer tracer
;
215 map
.push_back(InjectionArc(0, 1, true));
216 map
.push_back(InjectionArc(0, 2, false));
218 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
219 ASSERT_EQ(3u, tracer
.actions().size());
220 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
221 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
222 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::CLOSE
, 0));
225 TEST(FileDescriptorShuffleTest
, FanoutAndClose2
) {
226 InjectiveMultimap map
;
227 InjectionTracer tracer
;
228 map
.push_back(InjectionArc(0, 1, false));
229 map
.push_back(InjectionArc(0, 2, true));
231 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
232 ASSERT_EQ(3u, tracer
.actions().size());
233 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
234 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
235 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::CLOSE
, 0));
238 TEST(FileDescriptorShuffleTest
, FanoutAndClose3
) {
239 InjectiveMultimap map
;
240 InjectionTracer tracer
;
241 map
.push_back(InjectionArc(0, 1, true));
242 map
.push_back(InjectionArc(0, 2, true));
244 EXPECT_TRUE(PerformInjectiveMultimap(map
, &tracer
));
245 ASSERT_EQ(3u, tracer
.actions().size());
246 EXPECT_TRUE(tracer
.actions()[0] == Action(Action::MOVE
, 0, 1));
247 EXPECT_TRUE(tracer
.actions()[1] == Action(Action::MOVE
, 0, 2));
248 EXPECT_TRUE(tracer
.actions()[2] == Action(Action::CLOSE
, 0));
251 class FailingDelegate
: public InjectionDelegate
{
253 virtual bool Duplicate(int* result
, int fd
) OVERRIDE
{
257 virtual bool Move(int src
, int dest
) OVERRIDE
{
261 virtual void Close(int fd
) OVERRIDE
{}
264 TEST(FileDescriptorShuffleTest
, EmptyWithFailure
) {
265 InjectiveMultimap map
;
266 FailingDelegate failing
;
268 EXPECT_TRUE(PerformInjectiveMultimap(map
, &failing
));
271 TEST(FileDescriptorShuffleTest
, NoopWithFailure
) {
272 InjectiveMultimap map
;
273 FailingDelegate failing
;
274 map
.push_back(InjectionArc(0, 0, false));
276 EXPECT_TRUE(PerformInjectiveMultimap(map
, &failing
));
279 TEST(FileDescriptorShuffleTest
, Simple1WithFailure
) {
280 InjectiveMultimap map
;
281 FailingDelegate failing
;
282 map
.push_back(InjectionArc(0, 1, false));
284 EXPECT_FALSE(PerformInjectiveMultimap(map
, &failing
));