1 /*
2  * Copyright (C) 2021 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 #include <cutils/ashmem.h>
18 #include <gtest/gtest.h>
19 
20 #include <MappedFile.h>
21 #include <SharedMemory.h>
22 #include <errno.h>
23 #include <sys/mman.h>
24 
25 #include <memory>
26 
27 namespace {
28 
29 using ::android::OK;
30 using ::android::automotive::car_binder_lib::MappedFile;
31 using ::android::automotive::car_binder_lib::SharedMemory;
32 using ::android::base::borrowed_fd;
33 using ::android::base::unique_fd;
34 
35 constexpr size_t TEST_SIZE = 1024;
36 
TEST(MappedFileSharedMemoryTest,testSharedMemoryInvalidFd)37 TEST(MappedFileSharedMemoryTest, testSharedMemoryInvalidFd) {
38     unique_fd fd(-1);
39     SharedMemory sm(std::move(fd));
40 
41     ASSERT_FALSE(sm.isValid());
42     ASSERT_NE(OK, sm.getErr());
43 }
44 
TEST(MappedFileSharedMemoryTest,testSharedMemoryInvalidAshmemUniqueFd)45 TEST(MappedFileSharedMemoryTest, testSharedMemoryInvalidAshmemUniqueFd) {
46     unique_fd fd(0);
47     SharedMemory sm(std::move(fd));
48 
49     ASSERT_FALSE(sm.isValid());
50 }
51 
TEST(MappedFileSharedMemoryTest,testSharedMemoryInvalidAshmemBorrowedFd)52 TEST(MappedFileSharedMemoryTest, testSharedMemoryInvalidAshmemBorrowedFd) {
53     borrowed_fd fd(0);
54     SharedMemory sm(std::move(fd));
55 
56     ASSERT_FALSE(sm.isValid());
57 }
58 
testSharedMemoryMapRead(const SharedMemory & sm)59 void testSharedMemoryMapRead(const SharedMemory& sm) {
60     std::unique_ptr<MappedFile> mappedFile = sm.mapReadOnly();
61 
62     ASSERT_TRUE(mappedFile->isValid());
63     ASSERT_EQ(OK, mappedFile->getErr());
64 }
65 
TEST(MappedFileSharedMemoryTest,testSharedMemoryWithFdMapRead)66 TEST(MappedFileSharedMemoryTest, testSharedMemoryWithFdMapRead) {
67     unique_fd fd(ashmem_create_region("SharedMemory", TEST_SIZE));
68     ASSERT_TRUE(fd.ok());
69     SharedMemory sm(std::move(fd));
70 
71     ASSERT_TRUE(sm.isValid());
72     ASSERT_EQ(OK, sm.getErr());
73 
74     testSharedMemoryMapRead(sm);
75 }
76 
TEST(MappedFileSharedMemoryTest,testSharedMemoryWithSizeMapRead)77 TEST(MappedFileSharedMemoryTest, testSharedMemoryWithSizeMapRead) {
78     SharedMemory sm(TEST_SIZE);
79 
80     ASSERT_TRUE(sm.isValid());
81     ASSERT_EQ(OK, sm.getErr());
82 
83     testSharedMemoryMapRead(sm);
84 }
85 
testSharedMemoryMapWriteAndRead(const SharedMemory & sm)86 void testSharedMemoryMapWriteAndRead(const SharedMemory& sm) {
87     std::unique_ptr<MappedFile> writeFile = sm.mapReadWrite();
88 
89     ASSERT_TRUE(writeFile->isValid());
90     ASSERT_EQ(OK, writeFile->getErr());
91 
92     // Write something into the file.
93     uint8_t buffer[TEST_SIZE];
94     memset(buffer, 0xff, sizeof(buffer));
95     void* addr = writeFile->getWriteAddr();
96     memcpy(addr, buffer, sizeof(buffer));
97     writeFile->sync();
98 
99     // Try to read using a readonly map.
100     std::unique_ptr<MappedFile> readFile = sm.mapReadOnly();
101 
102     ASSERT_TRUE(readFile->isValid());
103     ASSERT_EQ(OK, readFile->getErr());
104 
105     const void* readAddr = readFile->getAddr();
106 
107     ASSERT_EQ(0, memcmp(readAddr, buffer, sizeof(buffer)));
108 }
109 
TEST(MappedFileSharedMemoryTest,testSharedMemoryWithOwnedFdMapWriteAndRead)110 TEST(MappedFileSharedMemoryTest, testSharedMemoryWithOwnedFdMapWriteAndRead) {
111     unique_fd fd(ashmem_create_region("SharedMemory", TEST_SIZE));
112     ASSERT_TRUE(fd.ok());
113     SharedMemory sm(std::move(fd));
114 
115     ASSERT_TRUE(sm.isValid());
116     ASSERT_EQ(OK, sm.getErr());
117 
118     testSharedMemoryMapWriteAndRead(sm);
119 }
120 
TEST(MappedFileSharedMemoryTest,testSharedMemoryWithSizeMapWriteAndRead)121 TEST(MappedFileSharedMemoryTest, testSharedMemoryWithSizeMapWriteAndRead) {
122     SharedMemory sm(TEST_SIZE);
123 
124     ASSERT_TRUE(sm.isValid());
125     ASSERT_EQ(OK, sm.getErr());
126 
127     testSharedMemoryMapWriteAndRead(sm);
128 }
129 
TEST(MappedFileSharedMemoryTest,testSharedMemoryWithBorrowedFdMapWriteAndRead)130 TEST(MappedFileSharedMemoryTest, testSharedMemoryWithBorrowedFdMapWriteAndRead) {
131     unique_fd fd(ashmem_create_region("SharedMemory", TEST_SIZE));
132     ASSERT_TRUE(fd.ok());
133 
134     borrowed_fd bfd(fd);
135     SharedMemory sm(bfd);
136 
137     ASSERT_TRUE(sm.isValid());
138     ASSERT_EQ(OK, sm.getErr());
139 
140     testSharedMemoryMapWriteAndRead(sm);
141 }
142 
TEST(MappedFileSharedMemoryTest,testSharedMemoryLock)143 TEST(MappedFileSharedMemoryTest, testSharedMemoryLock) {
144     SharedMemory sm(TEST_SIZE);
145 
146     std::unique_ptr<MappedFile> writeFile = sm.mapReadWrite();
147 
148     ASSERT_TRUE(writeFile->isValid());
149 
150     sm.lock();
151 
152     std::unique_ptr<MappedFile> readFile = sm.mapReadOnly();
153 
154     ASSERT_TRUE(readFile->isValid());
155 
156     // sm.mapReadWrite() after lock would panic.
157     int fd = sm.getFd();
158     void* addr = mmap(NULL, TEST_SIZE, PROT_WRITE, MAP_SHARED, fd, 0);
159 
160     ASSERT_EQ(addr, MAP_FAILED);
161 }
162 
163 }  //  namespace
164