blob: b005af105c9d4ea2315c3714e3e41f3bad28398c [file] [log] [blame]
Hridya Valsaraju10153822016-06-27 14:07:14 -07001/*
2 * Copyright (C) 2016 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 <asm-generic/mman.h>
18#include <cutils/ashmem.h>
19#include <gtest/gtest.h>
20#include <cstdlib>
21#include <sstream>
22#include "common/MessageQueue.h"
23
24static const int queue_size = 1024;
25typedef uint64_t mq_position_t;
26
27class MQTests : public ::testing::Test {
28 protected:
29 virtual void TearDown() {
30 if (fmsgq) {
31 delete fmsgq;
32 }
33 }
34
35 virtual void SetUp() {
36 size_t eventQueueTotal = 4096;
37 int ashmemFd = ashmem_create_region("MessageQueue", eventQueueTotal);
38 ashmem_set_prot_region(ashmemFd, PROT_READ | PROT_WRITE);
39 ASSERT_TRUE(ashmemFd >= 0);
40 native_handle_t* mq_handle = native_handle_create(1, 0);
41 ASSERT_TRUE(mq_handle != nullptr);
Iliyan Malchev7e628762016-08-01 09:21:46 -070042 std::vector<android::hardware::GrantorDescriptor> Grantors(
Hridya Valsaraju10153822016-06-27 14:07:14 -070043 MINIMUM_GRANTOR_COUNT);
44 /*
45 * The native handle will contain the fds to be
46 * mapped.
47 */
48 mq_handle->data[0] = ashmemFd;
49
50 /*
51 * Create Grantor Descriptors for read, write pointers and the data
52 * buffer.
53 */
Iliyan Malchev7e628762016-08-01 09:21:46 -070054 Grantors[android::hardware::READPTRPOS] = {0, 0, 0, sizeof(mq_position_t)};
55 Grantors[android::hardware::WRITEPTRPOS] = {0, 0, sizeof(mq_position_t),
Hridya Valsaraju10153822016-06-27 14:07:14 -070056 sizeof(mq_position_t)};
Iliyan Malchev7e628762016-08-01 09:21:46 -070057 Grantors[android::hardware::DATAPTRPOS] = {0, 0, 2 * sizeof(mq_position_t),
Hridya Valsaraju10153822016-06-27 14:07:14 -070058 queue_size};
Iliyan Malchev7e628762016-08-01 09:21:46 -070059 android::hardware::MQDescriptor mydesc(Grantors, mq_handle, 0, sizeof(uint8_t));
60 fmsgq = new android::hardware::MessageQueue<uint8_t>(mydesc);
Hridya Valsaraju10153822016-06-27 14:07:14 -070061 ASSERT_TRUE(fmsgq != nullptr);
62 ASSERT_TRUE(fmsgq->isValid());
63 }
64
Iliyan Malchev7e628762016-08-01 09:21:46 -070065 android::hardware::MessageQueue<uint8_t>* fmsgq;
Hridya Valsaraju10153822016-06-27 14:07:14 -070066};
67
68/*
69 * Verify that a few bytes of data can be successfully written and read.
70 */
71TEST_F(MQTests, SmallInputTest1) {
72 const int data_len = 16;
73 int write_count = -1;
74 ASSERT_TRUE(data_len <= queue_size);
75 uint8_t data[data_len];
76 for (int i = 0; i < data_len; i++) {
77 data[i] = i & 0xFF;
78 }
79 ASSERT_TRUE(fmsgq->write(data, data_len));
80 uint8_t read_data[data_len] = {};
81 ASSERT_TRUE(fmsgq->read(read_data, data_len));
82 ASSERT_TRUE(memcmp(data, read_data, data_len) == 0);
83}
84
85/*
86 * Verify that read() returns false when trying to read from an empty queue.
87 */
88TEST_F(MQTests, ReadWhenEmpty) {
89 ASSERT_TRUE(fmsgq->availableToRead() == 0);
90 const int data_len = 2;
91 ASSERT_TRUE(data_len < queue_size);
92 uint8_t read_data[data_len];
93 ASSERT_FALSE(fmsgq->read(read_data, data_len));
94}
95
96/*
97 * Write the queue when full. Verify that subsequent writes fail.
98 * Verify that availableToWrite() returns 0 as expected.
99 */
100
101TEST_F(MQTests, WriteWhenFull) {
102 ASSERT_TRUE(fmsgq->availableToRead() == 0);
103 uint8_t* data = new uint8_t[queue_size];
104 for (int i = 0; i < queue_size; i++) {
105 data[i] = i & 0xFF;
106 }
107 ASSERT_TRUE(fmsgq->write(data, queue_size));
108 ASSERT_TRUE(fmsgq->availableToWrite() == 0);
109 ASSERT_FALSE(fmsgq->write(data, 1));
110
111 uint8_t* read_data = new uint8_t[queue_size]();
112 ASSERT_TRUE(fmsgq->read(read_data, queue_size));
113 ASSERT_TRUE(memcmp(data, read_data, queue_size) == 0);
114
115 delete[] data;
116 delete[] read_data;
117}
118
119/*
120 * Write a chunk of data equal to the queue size.
121 * Verify that the write is successful and the subsequent read
122 * returns the expected data.
123 */
124TEST_F(MQTests, LargeInputTest1) {
125 uint8_t* data = new uint8_t[queue_size];
126 for (int i = 0; i < queue_size; i++) {
127 data[i] = i & 0xFF;
128 }
129 ASSERT_TRUE(fmsgq->write(data, queue_size));
130 uint8_t* read_data = new uint8_t[queue_size]();
131 ASSERT_TRUE(fmsgq->read(read_data, queue_size));
132 ASSERT_TRUE(memcmp(data, read_data, queue_size) == 0);
133 delete[] data;
134 delete[] read_data;
135}
136
137/*
138 * Attempt to write a chunk of data larger than the queue size.
139 * Verify that it fails. Verify that a subsequent read fails and
140 * the queue is still empty.
141 */
142TEST_F(MQTests, LargeInputTest2) {
143 ASSERT_TRUE(fmsgq->availableToRead() == 0);
144 const int data_len = 4096;
145 ASSERT_TRUE(data_len > queue_size);
146 uint8_t* data = new uint8_t[data_len];
147 for (int i = 0; i < data_len; i++) {
148 data[i] = i & 0xFF;
149 }
150 ASSERT_FALSE(fmsgq->write(data, data_len));
151 uint8_t* read_data = new uint8_t[queue_size]();
152 ASSERT_FALSE(fmsgq->read(read_data, queue_size));
153 ASSERT_FALSE(memcmp(data, read_data, queue_size) == 0);
154 ASSERT_TRUE(fmsgq->availableToRead() == 0);
155 delete[] data;
156 delete[] read_data;
157}
158
159/*
160 * After the queue is full, try to write more data. Verify that
161 * the attempt returns false. Verify that the attempt did not
162 * affect the pre-existing data in the queue.
163 */
164TEST_F(MQTests, LargeInputTest3) {
165 uint8_t* data = new uint8_t[queue_size];
166 for (int i = 0; i < queue_size; i++) {
167 data[i] = i & 0xFF;
168 }
169 ASSERT_TRUE(fmsgq->write(data, queue_size));
170 ASSERT_FALSE(fmsgq->write(data, 1));
171 uint8_t* read_data = new uint8_t[queue_size];
172 ASSERT_TRUE(fmsgq->read(read_data, queue_size));
173 ASSERT_TRUE(memcmp(read_data, data, queue_size) == 0);
174 delete[] data;
175 delete[] read_data;
176}
177/*
178 * Verify that multiple reads one after the other return expected data.
179 */
180TEST_F(MQTests, MultipleRead) {
181 const int chunkSize = 100;
182 const int chunkNum = 5;
183 const size_t data_len = chunkSize * chunkNum;
184 ASSERT_TRUE(data_len <= queue_size);
185 uint8_t data[data_len];
186 for (unsigned int i = 0; i < data_len; i++) {
187 data[i] = i & 0xFF;
188 }
189 ASSERT_TRUE(fmsgq->write(data, data_len));
190 uint8_t read_data[data_len] = {};
191 for (unsigned int i = 0; i < chunkNum; i++) {
192 ASSERT_TRUE(fmsgq->read(read_data + i * chunkSize, chunkSize));
193 }
194 ASSERT_TRUE(memcmp(read_data, data, data_len) == 0);
195}
196
197/*
198 * Verify that multiple writes one after the other happens correctly.
199 */
200TEST_F(MQTests, MultipleWrite) {
201 const int chunkSize = 100;
202 const int chunkNum = 5;
203 const size_t data_len = chunkSize * chunkNum;
204 ASSERT_TRUE(data_len <= queue_size);
205 uint8_t data[data_len];
206 for (unsigned int i = 0; i < data_len; i++) {
207 data[i] = i & 0xFF;
208 }
209 for (unsigned int i = 0; i < chunkNum; i++) {
210 ASSERT_TRUE(fmsgq->write(data + i * chunkSize, chunkSize));
211 }
212 uint8_t read_data[data_len] = {};
213 ASSERT_TRUE(fmsgq->read(read_data, data_len));
214 ASSERT_TRUE(memcmp(read_data, data, data_len) == 0);
215}
216
217/*
218 * Write enough messages into the FMQ to fill half of it
219 * and read back the same.
220 * Write queue_size messages into the queue. This will cause a
221 * wrap around. Read and verify the data.
222 */
223TEST_F(MQTests, ReadWriteWrapAround) {
224 size_t numMessages = queue_size / 2;
225 uint8_t* data = new uint8_t[queue_size];
226 uint8_t* read_data = new uint8_t[queue_size]();
227 for (int i = 0; i < queue_size; i++) {
228 data[i] = i & 0xFF;
229 }
230 ASSERT_TRUE(fmsgq->write(data, numMessages));
231 ASSERT_TRUE(fmsgq->read(read_data, numMessages));
232 ASSERT_TRUE(fmsgq->write(data, queue_size));
233 ASSERT_TRUE(fmsgq->read(read_data, queue_size));
234 ASSERT_TRUE(memcmp(read_data, data, queue_size) == 0);
235 delete[] data;
236 delete[] read_data;
237}