• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "base/posix/file_descriptor_shuffle.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7 
8 namespace {
9 
10 // 'Duplicated' file descriptors start at this number
11 const int kDuplicateBase = 1000;
12 
13 }  // namespace
14 
15 namespace base {
16 
17 struct Action {
18   enum Type {
19     CLOSE,
20     MOVE,
21     DUPLICATE,
22   };
23 
Actionbase::Action24   Action(Type in_type, int in_fd1, int in_fd2 = -1)
25       : type(in_type),
26         fd1(in_fd1),
27         fd2(in_fd2) {
28   }
29 
operator ==base::Action30   bool operator==(const Action& other) const {
31     return other.type == type &&
32            other.fd1 == fd1 &&
33            other.fd2 == fd2;
34   }
35 
36   Type type;
37   int fd1;
38   int fd2;
39 };
40 
41 class InjectionTracer : public InjectionDelegate {
42  public:
InjectionTracer()43   InjectionTracer()
44       : next_duplicate_(kDuplicateBase) {
45   }
46 
Duplicate(int * result,int fd)47   virtual bool Duplicate(int* result, int fd) OVERRIDE {
48     *result = next_duplicate_++;
49     actions_.push_back(Action(Action::DUPLICATE, *result, fd));
50     return true;
51   }
52 
Move(int src,int dest)53   virtual bool Move(int src, int dest) OVERRIDE {
54     actions_.push_back(Action(Action::MOVE, src, dest));
55     return true;
56   }
57 
Close(int fd)58   virtual void Close(int fd) OVERRIDE {
59     actions_.push_back(Action(Action::CLOSE, fd));
60   }
61 
actions() const62   const std::vector<Action>& actions() const { return actions_; }
63 
64  private:
65   int next_duplicate_;
66   std::vector<Action> actions_;
67 };
68 
TEST(FileDescriptorShuffleTest,Empty)69 TEST(FileDescriptorShuffleTest, Empty) {
70   InjectiveMultimap map;
71   InjectionTracer tracer;
72 
73   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
74   EXPECT_EQ(0u, tracer.actions().size());
75 }
76 
TEST(FileDescriptorShuffleTest,Noop)77 TEST(FileDescriptorShuffleTest, Noop) {
78   InjectiveMultimap map;
79   InjectionTracer tracer;
80   map.push_back(InjectionArc(0, 0, false));
81 
82   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
83   EXPECT_EQ(0u, tracer.actions().size());
84 }
85 
TEST(FileDescriptorShuffleTest,NoopAndClose)86 TEST(FileDescriptorShuffleTest, NoopAndClose) {
87   InjectiveMultimap map;
88   InjectionTracer tracer;
89   map.push_back(InjectionArc(0, 0, true));
90 
91   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
92   EXPECT_EQ(0u, tracer.actions().size());
93 }
94 
TEST(FileDescriptorShuffleTest,Simple1)95 TEST(FileDescriptorShuffleTest, Simple1) {
96   InjectiveMultimap map;
97   InjectionTracer tracer;
98   map.push_back(InjectionArc(0, 1, false));
99 
100   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
101   ASSERT_EQ(1u, tracer.actions().size());
102   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
103 }
104 
TEST(FileDescriptorShuffleTest,Simple2)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));
110 
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));
115 }
116 
TEST(FileDescriptorShuffleTest,Simple3)117 TEST(FileDescriptorShuffleTest, Simple3) {
118   InjectiveMultimap map;
119   InjectionTracer tracer;
120   map.push_back(InjectionArc(0, 1, true));
121 
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));
126 }
127 
TEST(FileDescriptorShuffleTest,Simple4)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));
133 
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));
138 }
139 
TEST(FileDescriptorShuffleTest,Cycle)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));
145 
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));
153 }
154 
TEST(FileDescriptorShuffleTest,CycleAndClose1)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));
160 
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));
168 }
169 
TEST(FileDescriptorShuffleTest,CycleAndClose2)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));
175 
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));
183 }
184 
TEST(FileDescriptorShuffleTest,CycleAndClose3)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));
190 
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));
198 }
199 
TEST(FileDescriptorShuffleTest,Fanout)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));
205 
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));
210 }
211 
TEST(FileDescriptorShuffleTest,FanoutAndClose1)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));
217 
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));
223 }
224 
TEST(FileDescriptorShuffleTest,FanoutAndClose2)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));
230 
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));
236 }
237 
TEST(FileDescriptorShuffleTest,FanoutAndClose3)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));
243 
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));
249 }
250 
251 class FailingDelegate : public InjectionDelegate {
252  public:
Duplicate(int * result,int fd)253   virtual bool Duplicate(int* result, int fd) OVERRIDE {
254     return false;
255   }
256 
Move(int src,int dest)257   virtual bool Move(int src, int dest) OVERRIDE {
258     return false;
259   }
260 
Close(int fd)261   virtual void Close(int fd) OVERRIDE {}
262 };
263 
TEST(FileDescriptorShuffleTest,EmptyWithFailure)264 TEST(FileDescriptorShuffleTest, EmptyWithFailure) {
265   InjectiveMultimap map;
266   FailingDelegate failing;
267 
268   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
269 }
270 
TEST(FileDescriptorShuffleTest,NoopWithFailure)271 TEST(FileDescriptorShuffleTest, NoopWithFailure) {
272   InjectiveMultimap map;
273   FailingDelegate failing;
274   map.push_back(InjectionArc(0, 0, false));
275 
276   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
277 }
278 
TEST(FileDescriptorShuffleTest,Simple1WithFailure)279 TEST(FileDescriptorShuffleTest, Simple1WithFailure) {
280   InjectiveMultimap map;
281   FailingDelegate failing;
282   map.push_back(InjectionArc(0, 1, false));
283 
284   EXPECT_FALSE(PerformInjectiveMultimap(map, &failing));
285 }
286 
287 }  // namespace base
288