1 #![cfg(test)]
2
3 use crate::sys::{lender_msg, lender_region};
4 use core::ffi::CStr;
5 use tipc::{Deserialize, Handle, MMapFlags, Serialize, Serializer, TipcError, UnsafeSharedBuf};
6
7 #[allow(bad_style)]
8 #[allow(dead_code)] // Needed because not all variants of the `lender_command` enum are used.
9 #[allow(deref_nullptr)] // https://github.com/rust-lang/rust-bindgen/issues/1651
10 mod sys {
11 include!(env!("BINDGEN_INC_FILE"));
12 }
13
14 test::init!();
15
16 const LENDER_PORT: &[u8] = b"com.android.memref.lender\0";
17
18 #[test]
recv_ref()19 fn recv_ref() {
20 // Connect to the lender service.
21 let port = CStr::from_bytes_with_nul(LENDER_PORT).unwrap();
22 let lender = Handle::connect(port).unwrap();
23
24 // Request the shared buffer from the lender service.
25 let remote_handle = request_remote_buf(&lender);
26
27 // Try to mmap the shared buffer into process memory.
28 //
29 // NOTE: Try to map with size 2 in order to test the logic for rounding up to a
30 // multiple of the page size. The lender service will always allocate a buffer
31 // of exactly one page, but we only ever read/write the first two bytes, so this
32 // should still map correctly.
33 let remote_buf =
34 remote_handle.mmap(2, MMapFlags::ReadWrite).expect("Failed to map the shared buffer");
35
36 // Run the main test logic.
37 test_read_write(&lender, remote_buf);
38 }
39
40 #[test]
drop_shared_buf_handle()41 fn drop_shared_buf_handle() {
42 // Connect to the lender service.
43 let port = CStr::from_bytes_with_nul(LENDER_PORT).unwrap();
44 let lender = Handle::connect(port).unwrap();
45
46 // Request the shared buffer from the lender service.
47 let remote_handle = request_remote_buf(&lender);
48
49 // Map the buffer into memory and then drop the `Handle` associated with it.
50 // This should not invalidate the buffer.
51 let remote_buf =
52 remote_handle.mmap(2, MMapFlags::ReadWrite).expect("Failed to map the shared buffer");
53 std::mem::drop(remote_handle);
54
55 // Run the main test logic to verify that the shared buffer is still valid after
56 // closing the associated handle.
57 test_read_write(&lender, remote_buf);
58 }
59
60 /// Makes the initial request to the lender service for the remote buffer.
request_remote_buf(lender: &Handle) -> Handle61 fn request_remote_buf(lender: &Handle) -> Handle {
62 // Send a command to the lender service telling it we want to receive a shared
63 // memory buffer.
64 lender
65 .send(&lender_msg { cmd: sys::lender_command_LENDER_LEND_BSS, region: Default::default() })
66 .unwrap();
67
68 // Receive the memref from the lender service.
69 let recv_buf = &mut [0; 0][..];
70 let resp = lender.recv::<MemrefResponse>(recv_buf).unwrap();
71
72 resp.handle
73 }
74
75 /// Runs the logic to test writing to and reading from the shared buffer.
test_read_write(lender: &Handle, remote_buf: UnsafeSharedBuf)76 fn test_read_write(lender: &Handle, remote_buf: UnsafeSharedBuf) {
77 // Check the initial state of the remote buffer after mapping.
78 //
79 // SAFETY: Reading a single `u8` from the remote buffer.
80 assert_eq!(4096, remote_buf.len());
81 assert_eq!(0, unsafe { remote_buf.ptr().read() });
82
83 // Write to the shared buffer and then ask the lender service to read from the
84 // buffer and send back to us the value it sees.
85 //
86 // SAFETY: Writing a single `u8` to the shared buffer.
87 unsafe { remote_buf.ptr().write(7) };
88
89 lender
90 .send(&lender_msg {
91 cmd: sys::lender_command_LENDER_READ_BSS,
92 region: lender_region { offset: 0, size: 1 },
93 })
94 .unwrap();
95
96 let recv_buf = &mut [0; 1][..];
97 let resp = lender.recv::<ReadResponse>(recv_buf).unwrap();
98
99 // Verify that the lender service read the same value that we wrote.
100 assert_eq!(7, resp.value);
101
102 // Send the lender service a value to write into the buffer. We tell it to write
103 // into the second byte of the buffer so that we can also verify that the first
104 // byte is not modified.
105 lender
106 .send(&WriteRequest {
107 msg: lender_msg {
108 cmd: sys::lender_command_LENDER_WRITE_BSS,
109 region: lender_region { offset: 1, size: 1 },
110 },
111 value: 123,
112 })
113 .unwrap();
114
115 let recv_buf = &mut [0; 0][..];
116 lender.recv::<WriteResponse>(recv_buf).unwrap();
117
118 // Verify that the value we sent was written to the specified offset in the
119 // shared buffer.
120 //
121 // SAFETY: Reading the first two bytes of the shared buffer.
122 assert_eq!(7, unsafe { remote_buf.ptr().read() });
123 assert_eq!(123, unsafe { remote_buf.ptr().offset(1).read() });
124
125 // Reset the buffer since it's shared between test runs.
126 //
127 // SAFETY: Writing to the first two bytes of the shared buffer.
128 unsafe {
129 remote_buf.ptr().write(0);
130 remote_buf.ptr().offset(1).write(0);
131 }
132
133 remote_buf.unmap();
134 }
135
136 impl<'s> Serialize<'s> for lender_msg {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>137 fn serialize<'a: 's, S: Serializer<'s>>(
138 &'a self,
139 serializer: &mut S,
140 ) -> Result<S::Ok, S::Error> {
141 // SAFETY: `lender_msg` is generated from the C header and already matches the
142 // expected layout.
143 unsafe { serializer.serialize_as_bytes(self) }
144 }
145 }
146
147 impl Default for lender_region {
default() -> Self148 fn default() -> Self {
149 lender_region { offset: 0, size: 0 }
150 }
151 }
152
153 /// Response type for the `LENDER_LEND_BSS` command.
154 struct MemrefResponse {
155 handle: Handle,
156 }
157
158 impl Deserialize for MemrefResponse {
159 type Error = TipcError;
160 const MAX_SERIALIZED_SIZE: usize = 0;
161
deserialize(_bytes: &[u8], handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>162 fn deserialize(_bytes: &[u8], handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
163 assert_eq!(1, handles.len());
164 let handle = handles[0].take().unwrap();
165 Ok(MemrefResponse { handle })
166 }
167 }
168
169 /// Response type for the `LENDER_READ_BSS` command.
170 struct ReadResponse {
171 value: u8,
172 }
173
174 impl Deserialize for ReadResponse {
175 type Error = TipcError;
176 const MAX_SERIALIZED_SIZE: usize = 1;
177
deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>178 fn deserialize(bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
179 Ok(ReadResponse { value: bytes[0] })
180 }
181 }
182
183 /// Request type for the `LENDER_WRITE_BSS` command, which includes an additional
184 /// byte value to write.
185 struct WriteRequest {
186 msg: lender_msg,
187 value: u8,
188 }
189
190 impl<'s> Serialize<'s> for WriteRequest {
serialize<'a: 's, S: Serializer<'s>>( &'a self, serializer: &mut S, ) -> Result<S::Ok, S::Error>191 fn serialize<'a: 's, S: Serializer<'s>>(
192 &'a self,
193 serializer: &mut S,
194 ) -> Result<S::Ok, S::Error> {
195 self.msg.serialize(serializer)?;
196
197 // SAFETY: Serializing a single `u8` value is always safe.
198 unsafe { serializer.serialize_as_bytes(&self.value) }
199 }
200 }
201
202 /// Empty response type for the `LENDER_WRITE_BSS` command.
203 struct WriteResponse;
204
205 impl Deserialize for WriteResponse {
206 type Error = TipcError;
207 const MAX_SERIALIZED_SIZE: usize = 0;
208
deserialize(_bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error>209 fn deserialize(_bytes: &[u8], _handles: &mut [Option<Handle>]) -> Result<Self, Self::Error> {
210 Ok(WriteResponse)
211 }
212 }
213