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 |