• 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   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   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   void Close(int fd) override { actions_.push_back(Action(Action::CLOSE, fd)); }
59 
actions() const60   const std::vector<Action>& actions() const { return actions_; }
61 
62  private:
63   int next_duplicate_;
64   std::vector<Action> actions_;
65 };
66 
TEST(FileDescriptorShuffleTest,Empty)67 TEST(FileDescriptorShuffleTest, Empty) {
68   InjectiveMultimap map;
69   InjectionTracer tracer;
70 
71   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
72   EXPECT_EQ(0u, tracer.actions().size());
73 }
74 
TEST(FileDescriptorShuffleTest,Noop)75 TEST(FileDescriptorShuffleTest, Noop) {
76   InjectiveMultimap map;
77   InjectionTracer tracer;
78   map.push_back(InjectionArc(0, 0, false));
79 
80   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
81   EXPECT_EQ(0u, tracer.actions().size());
82 }
83 
TEST(FileDescriptorShuffleTest,NoopAndClose)84 TEST(FileDescriptorShuffleTest, NoopAndClose) {
85   InjectiveMultimap map;
86   InjectionTracer tracer;
87   map.push_back(InjectionArc(0, 0, true));
88 
89   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
90   EXPECT_EQ(0u, tracer.actions().size());
91 }
92 
TEST(FileDescriptorShuffleTest,Simple1)93 TEST(FileDescriptorShuffleTest, Simple1) {
94   InjectiveMultimap map;
95   InjectionTracer tracer;
96   map.push_back(InjectionArc(0, 1, false));
97 
98   EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
99   ASSERT_EQ(1u, tracer.actions().size());
100   EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
101 }
102 
TEST(FileDescriptorShuffleTest,Simple2)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));
108 
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));
113 }
114 
TEST(FileDescriptorShuffleTest,Simple3)115 TEST(FileDescriptorShuffleTest, Simple3) {
116   InjectiveMultimap map;
117   InjectionTracer tracer;
118   map.push_back(InjectionArc(0, 1, true));
119 
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));
124 }
125 
TEST(FileDescriptorShuffleTest,Simple4)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));
131 
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));
136 }
137 
TEST(FileDescriptorShuffleTest,Cycle)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));
143 
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));
151 }
152 
TEST(FileDescriptorShuffleTest,CycleAndClose1)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));
158 
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));
166 }
167 
TEST(FileDescriptorShuffleTest,CycleAndClose2)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));
173 
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));
181 }
182 
TEST(FileDescriptorShuffleTest,CycleAndClose3)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));
188 
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));
196 }
197 
TEST(FileDescriptorShuffleTest,Fanout)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));
203 
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));
208 }
209 
TEST(FileDescriptorShuffleTest,FanoutAndClose1)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));
215 
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));
221 }
222 
TEST(FileDescriptorShuffleTest,FanoutAndClose2)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));
228 
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));
234 }
235 
TEST(FileDescriptorShuffleTest,FanoutAndClose3)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));
241 
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));
247 }
248 
249 class FailingDelegate : public InjectionDelegate {
250  public:
Duplicate(int * result,int fd)251   bool Duplicate(int* result, int fd) override { return false; }
252 
Move(int src,int dest)253   bool Move(int src, int dest) override { return false; }
254 
Close(int fd)255   void Close(int fd) override {}
256 };
257 
TEST(FileDescriptorShuffleTest,EmptyWithFailure)258 TEST(FileDescriptorShuffleTest, EmptyWithFailure) {
259   InjectiveMultimap map;
260   FailingDelegate failing;
261 
262   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
263 }
264 
TEST(FileDescriptorShuffleTest,NoopWithFailure)265 TEST(FileDescriptorShuffleTest, NoopWithFailure) {
266   InjectiveMultimap map;
267   FailingDelegate failing;
268   map.push_back(InjectionArc(0, 0, false));
269 
270   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
271 }
272 
TEST(FileDescriptorShuffleTest,Simple1WithFailure)273 TEST(FileDescriptorShuffleTest, Simple1WithFailure) {
274   InjectiveMultimap map;
275   FailingDelegate failing;
276   map.push_back(InjectionArc(0, 1, false));
277 
278   EXPECT_FALSE(PerformInjectiveMultimap(map, &failing));
279 }
280 
281 }  // namespace base
282