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