root/base/posix/file_descriptor_shuffle_unittest.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. Duplicate
  2. Move
  3. Close
  4. actions
  5. TEST
  6. TEST
  7. TEST
  8. TEST
  9. TEST
  10. TEST
  11. TEST
  12. TEST
  13. TEST
  14. TEST
  15. TEST
  16. TEST
  17. TEST
  18. TEST
  19. TEST
  20. Duplicate
  21. Move
  22. Close
  23. TEST
  24. TEST
  25. TEST

// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "base/posix/file_descriptor_shuffle.h"
#include "testing/gtest/include/gtest/gtest.h"

namespace {

// 'Duplicated' file descriptors start at this number
const int kDuplicateBase = 1000;

}  // namespace

namespace base {

struct Action {
  enum Type {
    CLOSE,
    MOVE,
    DUPLICATE,
  };

  Action(Type in_type, int in_fd1, int in_fd2 = -1)
      : type(in_type),
        fd1(in_fd1),
        fd2(in_fd2) {
  }

  bool operator==(const Action& other) const {
    return other.type == type &&
           other.fd1 == fd1 &&
           other.fd2 == fd2;
  }

  Type type;
  int fd1;
  int fd2;
};

class InjectionTracer : public InjectionDelegate {
 public:
  InjectionTracer()
      : next_duplicate_(kDuplicateBase) {
  }

  virtual bool Duplicate(int* result, int fd) OVERRIDE {
    *result = next_duplicate_++;
    actions_.push_back(Action(Action::DUPLICATE, *result, fd));
    return true;
  }

  virtual bool Move(int src, int dest) OVERRIDE {
    actions_.push_back(Action(Action::MOVE, src, dest));
    return true;
  }

  virtual void Close(int fd) OVERRIDE {
    actions_.push_back(Action(Action::CLOSE, fd));
  }

  const std::vector<Action>& actions() const { return actions_; }

 private:
  int next_duplicate_;
  std::vector<Action> actions_;
};

TEST(FileDescriptorShuffleTest, Empty) {
  InjectiveMultimap map;
  InjectionTracer tracer;

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  EXPECT_EQ(0u, tracer.actions().size());
}

TEST(FileDescriptorShuffleTest, Noop) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 0, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  EXPECT_EQ(0u, tracer.actions().size());
}

TEST(FileDescriptorShuffleTest, NoopAndClose) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 0, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  EXPECT_EQ(0u, tracer.actions().size());
}

TEST(FileDescriptorShuffleTest, Simple1) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(1u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
}

TEST(FileDescriptorShuffleTest, Simple2) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, false));
  map.push_back(InjectionArc(2, 3, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(2u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 2, 3));
}

TEST(FileDescriptorShuffleTest, Simple3) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(2u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::CLOSE, 0));
}

TEST(FileDescriptorShuffleTest, Simple4) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(10, 0, true));
  map.push_back(InjectionArc(1, 1, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(2u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 10, 0));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::CLOSE, 10));
}

TEST(FileDescriptorShuffleTest, Cycle) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, false));
  map.push_back(InjectionArc(1, 0, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(4u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] ==
              Action(Action::DUPLICATE, kDuplicateBase, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
  EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
}

TEST(FileDescriptorShuffleTest, CycleAndClose1) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, true));
  map.push_back(InjectionArc(1, 0, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(4u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] ==
              Action(Action::DUPLICATE, kDuplicateBase, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
  EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
}

TEST(FileDescriptorShuffleTest, CycleAndClose2) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, false));
  map.push_back(InjectionArc(1, 0, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(4u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] ==
              Action(Action::DUPLICATE, kDuplicateBase, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
  EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
}

TEST(FileDescriptorShuffleTest, CycleAndClose3) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, true));
  map.push_back(InjectionArc(1, 0, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(4u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] ==
              Action(Action::DUPLICATE, kDuplicateBase, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::MOVE, kDuplicateBase, 0));
  EXPECT_TRUE(tracer.actions()[3] == Action(Action::CLOSE, kDuplicateBase));
}

TEST(FileDescriptorShuffleTest, Fanout) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, false));
  map.push_back(InjectionArc(0, 2, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(2u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
}

TEST(FileDescriptorShuffleTest, FanoutAndClose1) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, true));
  map.push_back(InjectionArc(0, 2, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(3u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
}

TEST(FileDescriptorShuffleTest, FanoutAndClose2) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, false));
  map.push_back(InjectionArc(0, 2, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(3u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
}

TEST(FileDescriptorShuffleTest, FanoutAndClose3) {
  InjectiveMultimap map;
  InjectionTracer tracer;
  map.push_back(InjectionArc(0, 1, true));
  map.push_back(InjectionArc(0, 2, true));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &tracer));
  ASSERT_EQ(3u, tracer.actions().size());
  EXPECT_TRUE(tracer.actions()[0] == Action(Action::MOVE, 0, 1));
  EXPECT_TRUE(tracer.actions()[1] == Action(Action::MOVE, 0, 2));
  EXPECT_TRUE(tracer.actions()[2] == Action(Action::CLOSE, 0));
}

class FailingDelegate : public InjectionDelegate {
 public:
  virtual bool Duplicate(int* result, int fd) OVERRIDE {
    return false;
  }

  virtual bool Move(int src, int dest) OVERRIDE {
    return false;
  }

  virtual void Close(int fd) OVERRIDE {}
};

TEST(FileDescriptorShuffleTest, EmptyWithFailure) {
  InjectiveMultimap map;
  FailingDelegate failing;

  EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
}

TEST(FileDescriptorShuffleTest, NoopWithFailure) {
  InjectiveMultimap map;
  FailingDelegate failing;
  map.push_back(InjectionArc(0, 0, false));

  EXPECT_TRUE(PerformInjectiveMultimap(map, &failing));
}

TEST(FileDescriptorShuffleTest, Simple1WithFailure) {
  InjectiveMultimap map;
  FailingDelegate failing;
  map.push_back(InjectionArc(0, 1, false));

  EXPECT_FALSE(PerformInjectiveMultimap(map, &failing));
}

}  // namespace base

/* [<][>][^][v][top][bottom][index][help] */