Index: base/file_descriptor_shuffle_unittest.cc |
diff --git a/base/file_descriptor_shuffle_unittest.cc b/base/file_descriptor_shuffle_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..84d6c022361cef9181e983f82a259c5f8ee3f9b7 |
--- /dev/null |
+++ b/base/file_descriptor_shuffle_unittest.cc |
@@ -0,0 +1,290 @@ |
+// Copyright (c) 2009 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/file_descriptor_shuffle.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+ |
+using base::InjectiveMultimap; |
+using base::InjectionArc; |
+using base::PerformInjectiveMultimap; |
+using base::InjectionDelegate; |
+ |
+namespace { |
+typedef testing::Test FileDescriptorShuffleTest; |
+} |
+ |
+// 'Duplicated' file descriptors start at this number |
+static const int kDuplicateBase = 1000; |
+ |
+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) { |
+ } |
+ |
+ bool Duplicate(int* result, int fd) { |
+ *result = next_duplicate_++; |
+ actions_.push_back(Action(Action::DUPLICATE, *result, fd)); |
+ return true; |
+ } |
+ |
+ bool Move(int src, int dest) { |
+ actions_.push_back(Action(Action::MOVE, src, dest)); |
+ return true; |
+ } |
+ |
+ void Close(int fd) { |
+ 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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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)); |
+ EXPECT_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: |
+ bool Duplicate(int* result, int fd) { |
+ return false; |
+ } |
+ |
+ bool Move(int src, int dest) { |
+ return false; |
+ } |
+ |
+ void Close(int fd) { |
+ } |
+}; |
+ |
+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)); |
+} |
+ |