Home | History | Annotate | Download | only in base
      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 
     27   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 
     33   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:
     46   InjectionTracer()
     47       : next_duplicate_(kDuplicateBase) {
     48   }
     49 
     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 
     56   bool Move(int src, int dest) {
     57     actions_.push_back(Action(Action::MOVE, src, dest));
     58     return true;
     59   }
     60 
     61   void Close(int fd) {
     62     actions_.push_back(Action(Action::CLOSE, fd));
     63   }
     64 
     65   const std::vector<Action>& actions() const { return actions_; }
     66 
     67  private:
     68   int next_duplicate_;
     69   std::vector<Action> actions_;
     70 };
     71 
     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 
     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 
     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 
     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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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:
    256   bool Duplicate(int* result, int fd) {
    257     return false;
    258   }
    259 
    260   bool Move(int src, int dest) {
    261     return false;
    262   }
    263 
    264   void Close(int fd) {
    265   }
    266 };
    267 
    268 TEST(FileDescriptorShuffleTest, EmptyWithFailure) {
    269   InjectiveMultimap map;
    270   FailingDelegate failing;
    271 
    272   EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
    273 }
    274 
    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 
    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