| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 "files/public/c/lib/fd_table.h" | |
| 6 | |
| 7 #include <errno.h> | |
| 8 | |
| 9 #include <memory> | |
| 10 | |
| 11 #include "files/public/c/lib/fd_impl.h" | |
| 12 #include "files/public/c/tests/mock_errno_impl.h" | |
| 13 #include "testing/gtest/include/gtest/gtest.h" | |
| 14 | |
| 15 namespace mojio { | |
| 16 namespace { | |
| 17 | |
| 18 class TestFDImpl : public FDImpl { | |
| 19 public: | |
| 20 TestFDImpl() : FDImpl(nullptr) {} | |
| 21 ~TestFDImpl() override {} | |
| 22 | |
| 23 // |FDImpl| implementation: | |
| 24 bool Close() override { return false; } | |
| 25 std::unique_ptr<FDImpl> Dup() override { return nullptr; } | |
| 26 bool Ftruncate(mojio_off_t) override { return false; } | |
| 27 mojio_off_t Lseek(mojio_off_t, int) override { return -1; } | |
| 28 mojio_ssize_t Read(void*, size_t) override { return -1; } | |
| 29 mojio_ssize_t Write(const void*, size_t) override { return -1; } | |
| 30 bool Fstat(struct mojio_stat*) override { return false; } | |
| 31 | |
| 32 MOJO_DISALLOW_COPY_AND_ASSIGN(TestFDImpl); | |
| 33 }; | |
| 34 | |
| 35 TEST(FDTableTest, AddGetRemove) { | |
| 36 const int kLastErrorSentinel = -12345; | |
| 37 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 38 | |
| 39 FDTable fd_table(&errno_impl, 100); | |
| 40 | |
| 41 EXPECT_EQ(&errno_impl, fd_table.errno_impl()); | |
| 42 EXPECT_EQ(100u, fd_table.max_num_fds()); | |
| 43 | |
| 44 // Keep these as raw pointers, so we'll be able to check identity. | |
| 45 FDImpl* impl0 = new TestFDImpl(); | |
| 46 EXPECT_EQ(0, fd_table.Add(std::unique_ptr<FDImpl>(impl0))); | |
| 47 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 48 | |
| 49 // Should be able to get it. | |
| 50 errno_impl.Reset(kLastErrorSentinel); | |
| 51 EXPECT_EQ(impl0, fd_table.Get(0)); | |
| 52 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 53 | |
| 54 // Add a couple more. (FDs are allocated in order.) | |
| 55 errno_impl.Reset(kLastErrorSentinel); | |
| 56 FDImpl* impl1 = new TestFDImpl(); | |
| 57 EXPECT_EQ(1, fd_table.Add(std::unique_ptr<FDImpl>(impl1))); | |
| 58 FDImpl* impl2 = new TestFDImpl(); | |
| 59 EXPECT_EQ(2, fd_table.Add(std::unique_ptr<FDImpl>(impl2))); | |
| 60 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 61 | |
| 62 // Should still be able to get everything. | |
| 63 errno_impl.Reset(kLastErrorSentinel); | |
| 64 EXPECT_EQ(impl0, fd_table.Get(0)); | |
| 65 EXPECT_EQ(impl1, fd_table.Get(1)); | |
| 66 EXPECT_EQ(impl2, fd_table.Get(2)); | |
| 67 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 68 | |
| 69 // Remove 1. | |
| 70 errno_impl.Reset(kLastErrorSentinel); | |
| 71 std::unique_ptr<FDImpl> removed_impl1 = fd_table.Remove(1); | |
| 72 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 73 EXPECT_EQ(impl1, removed_impl1.get()); | |
| 74 // Note: Don't deallocate |impl1|/|removed_impl1|, so that |new_impl1| (below) | |
| 75 // definitely won't be allocated at the same address. | |
| 76 | |
| 77 // The next FD should be from the newly-vacated spot. | |
| 78 errno_impl.Reset(kLastErrorSentinel); | |
| 79 FDImpl* new_impl1 = new TestFDImpl(); | |
| 80 EXPECT_EQ(1, fd_table.Add(std::unique_ptr<FDImpl>(new_impl1))); | |
| 81 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 82 | |
| 83 errno_impl.Reset(kLastErrorSentinel); | |
| 84 EXPECT_EQ(new_impl1, fd_table.Get(1)); | |
| 85 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 86 | |
| 87 // Remove 0 and 2. | |
| 88 errno_impl.Reset(kLastErrorSentinel); | |
| 89 std::unique_ptr<FDImpl> removed_impl0 = fd_table.Remove(0); | |
| 90 std::unique_ptr<FDImpl> removed_impl2 = fd_table.Remove(2); | |
| 91 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 92 EXPECT_EQ(impl0, removed_impl0.get()); | |
| 93 EXPECT_EQ(impl2, removed_impl2.get()); | |
| 94 | |
| 95 // The next FD should be from the first vacant spot. | |
| 96 errno_impl.Reset(kLastErrorSentinel); | |
| 97 FDImpl* new_impl0 = new TestFDImpl(); | |
| 98 EXPECT_EQ(0, fd_table.Add(std::unique_ptr<FDImpl>(new_impl0))); | |
| 99 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 100 } | |
| 101 | |
| 102 TEST(FDTableTest, GetInvalid) { | |
| 103 const int kLastErrorSentinel = -12345; | |
| 104 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 105 FDTable fd_table(&errno_impl, 100); | |
| 106 | |
| 107 // Can't get 0 yet. Error should be EBADF. | |
| 108 EXPECT_EQ(nullptr, fd_table.Get(0)); | |
| 109 EXPECT_EQ(EBADF, errno_impl.Get()); | |
| 110 | |
| 111 // Add 0; should then be able to get 0. | |
| 112 errno_impl.Reset(kLastErrorSentinel); | |
| 113 EXPECT_EQ(0, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 114 EXPECT_TRUE(fd_table.Get(0)); | |
| 115 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 116 | |
| 117 // Can't get 1. | |
| 118 errno_impl.Reset(kLastErrorSentinel); | |
| 119 EXPECT_EQ(nullptr, fd_table.Get(1)); | |
| 120 EXPECT_EQ(EBADF, errno_impl.Get()); | |
| 121 } | |
| 122 | |
| 123 TEST(FDTableTest, RemoveInvalid) { | |
| 124 const int kLastErrorSentinel = -12345; | |
| 125 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 126 FDTable fd_table(&errno_impl, 100); | |
| 127 | |
| 128 // Can't remove 0 yet. Error should be EBADF. | |
| 129 EXPECT_EQ(nullptr, fd_table.Remove(0)); | |
| 130 EXPECT_EQ(EBADF, errno_impl.Get()); | |
| 131 | |
| 132 // Add 0; should then be able to remove 0. | |
| 133 errno_impl.Reset(kLastErrorSentinel); | |
| 134 EXPECT_EQ(0, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 135 EXPECT_TRUE(fd_table.Remove(0)); | |
| 136 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 137 | |
| 138 // But shouldn't be able to remove 0. | |
| 139 errno_impl.Reset(kLastErrorSentinel); | |
| 140 EXPECT_EQ(nullptr, fd_table.Remove(0)); | |
| 141 EXPECT_EQ(EBADF, errno_impl.Get()); | |
| 142 | |
| 143 // Nor 1. | |
| 144 errno_impl.Reset(kLastErrorSentinel); | |
| 145 EXPECT_EQ(nullptr, fd_table.Remove(1)); | |
| 146 EXPECT_EQ(EBADF, errno_impl.Get()); | |
| 147 } | |
| 148 | |
| 149 TEST(FDTableTest, Full) { | |
| 150 const int kLastErrorSentinel = -12345; | |
| 151 test::MockErrnoImpl errno_impl(kLastErrorSentinel); | |
| 152 FDTable fd_table(&errno_impl, 3); | |
| 153 | |
| 154 // Add 0, 1, 2. | |
| 155 EXPECT_EQ(0, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 156 EXPECT_EQ(1, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 157 EXPECT_EQ(2, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 158 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 159 | |
| 160 // Shouldn't be able to add another. Error should be EMFILE. (Note that this | |
| 161 // is EMFILE, which is too many open files (in the current process) and not | |
| 162 // ENFILE, which is too many open files in the system. | |
| 163 errno_impl.Reset(kLastErrorSentinel); | |
| 164 EXPECT_EQ(-1, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 165 EXPECT_EQ(EMFILE, errno_impl.Get()); | |
| 166 | |
| 167 // Remove 0. | |
| 168 errno_impl.Reset(kLastErrorSentinel); | |
| 169 EXPECT_TRUE(fd_table.Remove(0)); | |
| 170 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 171 | |
| 172 // Now adding should be okay again. | |
| 173 errno_impl.Reset(kLastErrorSentinel); | |
| 174 EXPECT_EQ(0, fd_table.Add(std::unique_ptr<FDImpl>(new TestFDImpl()))); | |
| 175 EXPECT_EQ(kLastErrorSentinel, errno_impl.Get()); // No error. | |
| 176 } | |
| 177 | |
| 178 } // namespace | |
| 179 } // namespace mojio | |
| OLD | NEW |