1 /*
2  * Copyright (C) 2015 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 
18 #include <vector>
19 
20 #include <errno.h>
21 #include <unistd.h>
22 
23 #include <android-base/unique_fd.h>
24 #include <binder/ParcelFileDescriptor.h>
25 
26 #include "aidl_test_client.h"
27 #include "gmock/gmock.h"
28 
29 using android::sp;
30 using android::base::unique_fd;
31 using android::binder::Status;
32 using android::os::ParcelFileDescriptor;
33 
34 using testing::Eq;
35 
36 struct FdTest : public AidlTest {
DoPipeFdTest37   void DoPipe(unique_fd* read_side, unique_fd* write_side) {
38     int fds[2];
39     int ret = pipe(fds);
40     ASSERT_THAT(ret, Eq(0));
41 
42     read_side->reset(fds[0]);
43     write_side->reset(fds[1]);
44   }
45 
WriteStringToFdFdTest46   void WriteStringToFd(const std::string& str, const unique_fd& fd) {
47     int wrote;
48     while ((wrote = write(fd.get(), str.data(), str.size())) < 0 && errno == EINTR)
49       ;
50     ASSERT_THAT(wrote, Eq((signed)str.size()));
51   }
52 
ReadFdToStringAndCompareFdTest53   void ReadFdToStringAndCompare(const unique_fd& fd, const std::string& str) {
54     size_t length = str.size();
55     int got;
56     std::string buf;
57     buf.resize(length);
58 
59     while ((got = read(fd.get(), &buf[0], length)) < 0 && errno == EINTR)
60       ;
61     ASSERT_THAT(buf, Eq(str));
62   }
63 };
64 
TEST_F(FdTest,fileDescriptor)65 TEST_F(FdTest, fileDescriptor) {
66   if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
67 
68   unique_fd read_fd;
69   unique_fd write_fd;
70   DoPipe(&read_fd, &write_fd);
71 
72   unique_fd return_fd;
73   auto status = cpp_java_tests->RepeatFileDescriptor(std::move(write_fd), &return_fd);
74   ASSERT_TRUE(status.isOk());
75 
76   /* A note on some of the spookier stuff going on here: IIUC writes to pipes
77    * should be atomic and non-blocking so long as the total size doesn't exceed
78    * PIPE_BUF. We thus play a bit fast and loose with failure modes here.
79    */
80   WriteStringToFd("ReturnString", return_fd);
81   ReadFdToStringAndCompare(read_fd, "ReturnString");
82 }
83 
TEST_F(FdTest,fileDescriptorArray)84 TEST_F(FdTest, fileDescriptorArray) {
85   if (!cpp_java_tests) GTEST_SKIP() << "Service does not support the CPP/Java-only tests.";
86 
87   std::vector<unique_fd> array;
88   array.resize(2);
89   DoPipe(&array[0], &array[1]);
90 
91   std::vector<unique_fd> repeated;
92 
93   if (backend == BackendType::JAVA) {
94     // other backends might require these to be valid FDs (not -1), since this
95     // isn't @nullable, but they don't require this to already be the correct
96     // size
97     repeated = std::vector<unique_fd>(array.size());
98   }
99 
100   std::vector<unique_fd> reversed;
101   auto status = cpp_java_tests->ReverseFileDescriptorArray(array, &repeated, &reversed);
102   ASSERT_TRUE(status.isOk()) << status;
103 
104   WriteStringToFd("First", array[1]);
105   WriteStringToFd("Second", repeated[1]);
106   WriteStringToFd("Third", reversed[0]);
107   ReadFdToStringAndCompare(reversed[1], "FirstSecondThird");
108 }
109 
TEST_F(FdTest,parcelFileDescriptor)110 TEST_F(FdTest, parcelFileDescriptor) {
111   unique_fd read_fd;
112   unique_fd write_fd;
113   DoPipe(&read_fd, &write_fd);
114 
115   ParcelFileDescriptor return_fd;
116   auto status =
117       service->RepeatParcelFileDescriptor(ParcelFileDescriptor(std::move(write_fd)), &return_fd);
118   ASSERT_TRUE(status.isOk());
119 
120   /* A note on some of the spookier stuff going on here: IIUC writes to pipes
121    * should be atomic and non-blocking so long as the total size doesn't exceed
122    * PIPE_BUF. We thus play a bit fast and loose with failure modes here.
123    */
124   WriteStringToFd("ReturnString", return_fd.release());
125   ReadFdToStringAndCompare(read_fd, "ReturnString");
126 }
127 
TEST_F(FdTest,parcelFileDescriptorArray)128 TEST_F(FdTest, parcelFileDescriptorArray) {
129   std::vector<unique_fd> array;
130   array.resize(2);
131   DoPipe(&array[0], &array[1]);
132 
133   std::vector<ParcelFileDescriptor> input;
134   for (auto& fd : array) {
135     input.push_back(ParcelFileDescriptor(std::move(fd)));
136   }
137 
138   std::vector<ParcelFileDescriptor> repeated;
139 
140   if (backend == BackendType::JAVA) {
141     // other backends might require these to be valid FDs (not -1), since this
142     // isn't @nullable, but they don't require this to already be the correct
143     // size
144     repeated = std::vector<ParcelFileDescriptor>(array.size());
145   }
146 
147   std::vector<ParcelFileDescriptor> reversed;
148   auto status = service->ReverseParcelFileDescriptorArray(input, &repeated, &reversed);
149   ASSERT_TRUE(status.isOk()) << status;
150 
151   WriteStringToFd("First", input[1].release());
152   WriteStringToFd("Second", repeated[1].release());
153   WriteStringToFd("Third", reversed[0].release());
154   ReadFdToStringAndCompare(input[0].release(), "FirstSecondThird");
155 }
156