1 // Copyright 2017 The Fuchsia 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 <fbl/unique_fd.h>
6 
7 #include <fbl/algorithm.h>
8 #include <unittest/unittest.h>
9 
10 #include <utility>
11 
12 namespace {
13 
invalid_fd_test()14 bool invalid_fd_test() {
15     BEGIN_TEST;
16 
17     {
18         fbl::unique_fd fd;
19 
20         EXPECT_EQ(fd.get(), fbl::unique_fd::InvalidValue());
21         EXPECT_EQ(fbl::unique_fd::InvalidValue(), fd.get());
22 
23         EXPECT_EQ(static_cast<int>(fd), fbl::unique_fd::InvalidValue());
24         EXPECT_EQ(fbl::unique_fd::InvalidValue(), static_cast<int>(fd));
25 
26         EXPECT_EQ(false, fd.is_valid());
27         EXPECT_EQ(static_cast<bool>(fd), false);
28         EXPECT_EQ(false, static_cast<bool>(fd));
29 
30         EXPECT_FALSE(fd);
31     }
32 
33     END_TEST;
34 }
35 
valid_comparison_test()36 bool valid_comparison_test() {
37     BEGIN_TEST;
38 
39     int pipes[2];
40     EXPECT_EQ(pipe(pipes), 0);
41     {
42         fbl::unique_fd in(pipes[1]);
43         fbl::unique_fd out(pipes[0]);
44 
45         EXPECT_NE(in.get(), fbl::unique_fd::InvalidValue());
46         EXPECT_NE(out.get(), fbl::unique_fd::InvalidValue());
47         EXPECT_NE(fbl::unique_fd::InvalidValue(), in.get());
48         EXPECT_NE(fbl::unique_fd::InvalidValue(), out.get());
49 
50         EXPECT_EQ(in.get(), in.get());
51         EXPECT_NE(in.get(), out.get());
52         EXPECT_FALSE(in == out);
53         EXPECT_TRUE(in == in);
54         EXPECT_TRUE(out == out);
55         EXPECT_EQ(pipes[1], in.get());
56 
57         EXPECT_TRUE(in);
58         EXPECT_TRUE(out);
59     }
60 
61     END_TEST;
62 }
63 
verify_pipes_open(int in,int out)64 bool verify_pipes_open(int in, int out) {
65     BEGIN_HELPER;
66     char w = 'a';
67     EXPECT_EQ(write(in, &w, 1), 1);
68     char r;
69     EXPECT_EQ(read(out, &r, 1), 1);
70     EXPECT_EQ(r, w);
71     END_HELPER;
72 }
73 
verify_pipes_closed(int in,int out)74 bool verify_pipes_closed(int in, int out) {
75     BEGIN_HELPER;
76     char c = 'a';
77     EXPECT_EQ(write(in, &c, 1), -1);
78     EXPECT_EQ(read(out, &c, 1), -1);
79     END_HELPER;
80 }
81 
scoping_test()82 bool scoping_test() {
83     BEGIN_TEST;
84     int pipes[2];
85     EXPECT_EQ(pipe(pipes), 0);
86     EXPECT_TRUE(verify_pipes_open(pipes[1], pipes[0]));
87     {
88         fbl::unique_fd in(pipes[1]);
89         fbl::unique_fd out(pipes[0]);
90 
91         EXPECT_EQ(pipes[0], out.get());
92         EXPECT_EQ(pipes[1], in.get());
93         EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
94     }
95     EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
96     END_TEST;
97 }
98 
swap_test()99 bool swap_test() {
100     BEGIN_TEST;
101     int pipes[2];
102     EXPECT_EQ(pipe(pipes), 0);
103     EXPECT_TRUE(verify_pipes_open(pipes[1], pipes[0]));
104     {
105         fbl::unique_fd in(pipes[1]);
106         fbl::unique_fd out(pipes[0]);
107 
108         in.swap(out);
109         EXPECT_EQ(pipes[0], in.get());
110         EXPECT_EQ(pipes[1], out.get());
111         EXPECT_TRUE(verify_pipes_open(out.get(), in.get()));
112     }
113     EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
114     EXPECT_TRUE(verify_pipes_closed(pipes[0], pipes[1]));
115     END_TEST;
116 }
117 
move_test()118 bool move_test() {
119     BEGIN_TEST;
120     // Move assignment
121     int pipes[2];
122     EXPECT_EQ(pipe(pipes), 0);
123     EXPECT_TRUE(verify_pipes_open(pipes[1], pipes[0]));
124     {
125         fbl::unique_fd in(pipes[1]);
126         fbl::unique_fd out(pipes[0]);
127 
128         fbl::unique_fd in2, out2;
129         EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
130         EXPECT_TRUE(verify_pipes_closed(in2.get(), out2.get()));
131 
132         in2 = std::move(in);
133         out2 = std::move(out);
134 
135         EXPECT_TRUE(verify_pipes_closed(in.get(), out.get()));
136         EXPECT_TRUE(verify_pipes_open(in2.get(), out2.get()));
137     }
138     EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
139 
140     // Move constructor
141     EXPECT_EQ(pipe(pipes), 0);
142     EXPECT_TRUE(verify_pipes_open(pipes[1], pipes[0]));
143     {
144         fbl::unique_fd in(pipes[1]);
145         fbl::unique_fd out(pipes[0]);
146 
147         EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
148 
149         fbl::unique_fd in2 = std::move(in);
150         fbl::unique_fd out2 = std::move(out);
151 
152         EXPECT_TRUE(verify_pipes_closed(in.get(), out.get()));
153         EXPECT_TRUE(verify_pipes_open(in2.get(), out2.get()));
154     }
155     EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
156     END_TEST;
157 }
158 
reset_test()159 bool reset_test() {
160     BEGIN_TEST;
161     int pipes[2];
162     EXPECT_EQ(pipe(pipes), 0);
163     int other_pipes[2];
164     EXPECT_EQ(pipe(other_pipes), 0);
165     EXPECT_TRUE(verify_pipes_open(pipes[1], pipes[0]));
166     EXPECT_TRUE(verify_pipes_open(other_pipes[1], other_pipes[0]));
167     {
168         fbl::unique_fd in(pipes[1]);
169         fbl::unique_fd out(pipes[0]);
170 
171         EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
172         EXPECT_TRUE(verify_pipes_open(pipes[1], pipes[0]));
173         EXPECT_TRUE(verify_pipes_open(other_pipes[1], other_pipes[0]));
174 
175         in.reset(other_pipes[1]);
176         out.reset(other_pipes[0]);
177 
178         EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
179         EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
180         EXPECT_TRUE(verify_pipes_open(other_pipes[1], other_pipes[0]));
181 
182         in.reset();
183         out.reset();
184 
185         EXPECT_TRUE(verify_pipes_closed(in.get(), out.get()));
186         EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
187         EXPECT_TRUE(verify_pipes_closed(other_pipes[1], other_pipes[0]));
188     }
189     EXPECT_TRUE(verify_pipes_closed(pipes[1], pipes[0]));
190     EXPECT_TRUE(verify_pipes_closed(other_pipes[1], other_pipes[0]));
191     END_TEST;
192 }
193 
duplicate_test()194 bool duplicate_test() {
195     BEGIN_TEST;
196     int pipes[2];
197     EXPECT_EQ(pipe(pipes), 0);
198 
199     fbl::unique_fd in(pipes[1]);
200     fbl::unique_fd out(pipes[0]);
201     EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
202     {
203         fbl::unique_fd in2 = in.duplicate();
204         fbl::unique_fd out2 = out.duplicate();
205         EXPECT_TRUE(verify_pipes_open(in2.get(), out2.get()));
206 
207         EXPECT_TRUE(verify_pipes_open(in2.get(), out.get()));
208         EXPECT_TRUE(verify_pipes_open(in.get(), out2.get()));
209         EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
210     }
211     EXPECT_TRUE(verify_pipes_open(in.get(), out.get()));
212 
213     END_TEST;
214 }
215 
216 } // namespace
217 
218 BEGIN_TEST_CASE(unique_fd_tests)
219 RUN_TEST(invalid_fd_test)
220 RUN_TEST(valid_comparison_test)
221 RUN_TEST(scoping_test)
222 RUN_TEST(swap_test)
223 RUN_TEST(move_test)
224 RUN_TEST(reset_test)
225 RUN_TEST(duplicate_test)
226 END_TEST_CASE(unique_fd_tests)
227