• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2009 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/file_descriptor_shuffle.h"
6 #include "testing/gtest/include/gtest/gtest.h"
7 
8 using base::InjectiveMultimap;
9 using base::InjectionArc;
10 using base::PerformInjectiveMultimap;
11 using base::InjectionDelegate;
12 
13 namespace {
14 typedef testing::Test FileDescriptorShuffleTest;
15 }
16 
17 // 'Duplicated' file descriptors start at this number
18 static const int kDuplicateBase = 1000;
19 
20 struct Action {
21   enum Type {
22     CLOSE,
23     MOVE,
24     DUPLICATE,
25   };
26 
ActionAction27   Action(Type in_type, int in_fd1, int in_fd2 = -1)
28       : type(in_type),
29         fd1(in_fd1),
30         fd2(in_fd2) {
31   }
32 
operator ==Action33   bool operator==(const Action& other) const {
34     return other.type == type &&
35            other.fd1 == fd1 &&
36            other.fd2 == fd2;
37   }
38 
39   Type type;
40   int fd1;
41   int fd2;
42 };
43 
44 class InjectionTracer : public InjectionDelegate {
45  public:
InjectionTracer()46   InjectionTracer()
47       : next_duplicate_(kDuplicateBase) {
48   }
49 
Duplicate(int * result,int fd)50   bool Duplicate(int* result, int fd) {
51     *result = next_duplicate_++;
52     actions_.push_back(Action(Action::DUPLICATE, *result, fd));
53     return true;
54   }
55 
Move(int src,int dest)56   bool Move(int src, int dest) {
57     actions_.push_back(Action(Action::MOVE, src, dest));
58     return true;
59   }
60 
Close(int fd)61   void Close(int fd) {
62     actions_.push_back(Action(Action::CLOSE, fd));
63   }
64 
actions() const65   const std::vector<Action>& actions() const { return actions_; }
66 
67  private:
68   int next_duplicate_;
69   std::vector<Action> actions_;
70 };
71 
TEST(FileDescriptorShuffleTest,Empty)72 TEST(FileDescriptorShuffleTest, Empty) {
73   InjectiveMultimap map;
74   InjectionTracer tracer;
75 
76   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
77   EXPECT_EQ(0u, tracer.actions().size());
78 }
79 
TEST(FileDescriptorShuffleTest,Noop)80 TEST(FileDescriptorShuffleTest, Noop) {
81   InjectiveMultimap map;
82   InjectionTracer tracer;
83   map.push_back(InjectionArc(0, 0, false));
84 
85   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
86   EXPECT_EQ(0u, tracer.actions().size());
87 }
88 
TEST(FileDescriptorShuffleTest,NoopAndClose)89 TEST(FileDescriptorShuffleTest, NoopAndClose) {
90   InjectiveMultimap map;
91   InjectionTracer tracer;
92   map.push_back(InjectionArc(0, 0, true));
93 
94   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
95   EXPECT_EQ(0u, tracer.actions().size());
96 }
97 
TEST(FileDescriptorShuffleTest,Simple1)98 TEST(FileDescriptorShuffleTest, Simple1) {
99   InjectiveMultimap map;
100   InjectionTracer tracer;
101   map.push_back(InjectionArc(0, 1, false));
102 
103   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
104   ASSERT_EQ(1u, tracer.actions().size());
105   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
106 }
107 
TEST(FileDescriptorShuffleTest,Simple2)108 TEST(FileDescriptorShuffleTest, Simple2) {
109   InjectiveMultimap map;
110   InjectionTracer tracer;
111   map.push_back(InjectionArc(0, 1, false));
112   map.push_back(InjectionArc(2, 3, false));
113 
114   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
115   ASSERT_EQ(2u, tracer.actions().size());
116   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
117   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 2, 3));
118 }
119 
TEST(FileDescriptorShuffleTest,Simple3)120 TEST(FileDescriptorShuffleTest, Simple3) {
121   InjectiveMultimap map;
122   InjectionTracer tracer;
123   map.push_back(InjectionArc(0, 1, true));
124 
125   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
126   ASSERT_EQ(2u, tracer.actions().size());
127   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
128   EXPECT_TRUE(tracer.actions()[1] == Action(Action::CLOSE, 0));
129 }
130 
TEST(FileDescriptorShuffleTest,Simple4)131 TEST(FileDescriptorShuffleTest, Simple4) {
132   InjectiveMultimap map;
133   InjectionTracer tracer;
134   map.push_back(InjectionArc(10, 0, true));
135   map.push_back(InjectionArc(1, 1, true));
136 
137   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
138   ASSERT_EQ(2u, tracer.actions().size());
139   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 10, 0));
140   EXPECT_TRUE(tracer.actions()[1] == Action(Action::CLOSE, 10));
141 }
142 
TEST(FileDescriptorShuffleTest,Cycle)143 TEST(FileDescriptorShuffleTest, Cycle) {
144   InjectiveMultimap map;
145   InjectionTracer tracer;
146   map.push_back(InjectionArc(0, 1, false));
147   map.push_back(InjectionArc(1, 0, false));
148 
149   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
150   ASSERT_EQ(4u, tracer.actions().size());
151   EXPECT_TRUE(tracer.actions()[0] ==
152               Action(Action::DUPLICATE, kDuplicateBase, 1));
153   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
154   EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
155   EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
156 }
157 
TEST(FileDescriptorShuffleTest,CycleAndClose1)158 TEST(FileDescriptorShuffleTest, CycleAndClose1) {
159   InjectiveMultimap map;
160   InjectionTracer tracer;
161   map.push_back(InjectionArc(0, 1, true));
162   map.push_back(InjectionArc(1, 0, false));
163 
164   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
165   ASSERT_EQ(4u, tracer.actions().size());
166   EXPECT_TRUE(tracer.actions()[0] ==
167               Action(Action::DUPLICATE, kDuplicateBase, 1));
168   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
169   EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
170   EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
171 }
172 
TEST(FileDescriptorShuffleTest,CycleAndClose2)173 TEST(FileDescriptorShuffleTest, CycleAndClose2) {
174   InjectiveMultimap map;
175   InjectionTracer tracer;
176   map.push_back(InjectionArc(0, 1, false));
177   map.push_back(InjectionArc(1, 0, true));
178 
179   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
180   ASSERT_EQ(4u, tracer.actions().size());
181   EXPECT_TRUE(tracer.actions()[0] ==
182               Action(Action::DUPLICATE, kDuplicateBase, 1));
183   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
184   EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
185   EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
186 }
187 
TEST(FileDescriptorShuffleTest,CycleAndClose3)188 TEST(FileDescriptorShuffleTest, CycleAndClose3) {
189   InjectiveMultimap map;
190   InjectionTracer tracer;
191   map.push_back(InjectionArc(0, 1, true));
192   map.push_back(InjectionArc(1, 0, true));
193 
194   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
195   ASSERT_EQ(4u, tracer.actions().size());
196   EXPECT_TRUE(tracer.actions()[0] ==
197               Action(Action::DUPLICATE, kDuplicateBase, 1));
198   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
199   EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
200   EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
201 }
202 
TEST(FileDescriptorShuffleTest,Fanout)203 TEST(FileDescriptorShuffleTest, Fanout) {
204   InjectiveMultimap map;
205   InjectionTracer tracer;
206   map.push_back(InjectionArc(0, 1, false));
207   map.push_back(InjectionArc(0, 2, false));
208 
209   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
210   ASSERT_EQ(2u, tracer.actions().size());
211   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
212   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
213 }
214 
TEST(FileDescriptorShuffleTest,FanoutAndClose1)215 TEST(FileDescriptorShuffleTest, FanoutAndClose1) {
216   InjectiveMultimap map;
217   InjectionTracer tracer;
218   map.push_back(InjectionArc(0, 1, true));
219   map.push_back(InjectionArc(0, 2, false));
220 
221   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
222   ASSERT_EQ(3u, tracer.actions().size());
223   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
224   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
225   EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
226 }
227 
TEST(FileDescriptorShuffleTest,FanoutAndClose2)228 TEST(FileDescriptorShuffleTest, FanoutAndClose2) {
229   InjectiveMultimap map;
230   InjectionTracer tracer;
231   map.push_back(InjectionArc(0, 1, false));
232   map.push_back(InjectionArc(0, 2, true));
233 
234   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
235   ASSERT_EQ(3u, tracer.actions().size());
236   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
237   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
238   EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
239 }
240 
TEST(FileDescriptorShuffleTest,FanoutAndClose3)241 TEST(FileDescriptorShuffleTest, FanoutAndClose3) {
242   InjectiveMultimap map;
243   InjectionTracer tracer;
244   map.push_back(InjectionArc(0, 1, true));
245   map.push_back(InjectionArc(0, 2, true));
246 
247   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
248   ASSERT_EQ(3u, tracer.actions().size());
249   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
250   EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
251   EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
252 }
253 
254 class FailingDelegate : public InjectionDelegate {
255  public:
Duplicate(int * result,int fd)256   bool Duplicate(int* result, int fd) {
257     return false;
258   }
259 
Move(int src,int dest)260   bool Move(int src, int dest) {
261     return false;
262   }
263 
Close(int fd)264   void Close(int fd) {
265   }
266 };
267 
TEST(FileDescriptorShuffleTest,EmptyWithFailure)268 TEST(FileDescriptorShuffleTest, EmptyWithFailure) {
269   InjectiveMultimap map;
270   FailingDelegate failing;
271 
272   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
273 }
274 
TEST(FileDescriptorShuffleTest,NoopWithFailure)275 TEST(FileDescriptorShuffleTest, NoopWithFailure) {
276   InjectiveMultimap map;
277   FailingDelegate failing;
278   map.push_back(InjectionArc(0, 0, false));
279 
280   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
281 }
282 
TEST(FileDescriptorShuffleTest,Simple1WithFailure)283 TEST(FileDescriptorShuffleTest, Simple1WithFailure) {
284   InjectiveMultimap map;
285   FailingDelegate failing;
286   map.push_back(InjectionArc(0, 1, false));
287 
288   EXPECT_FALSE(PerformInjectiveMultimap(map, &failing));
289 }
290