1 // Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include <fcntl.h>
6 #include <stdio.h>
7 #include <sys/mman.h>
8 #include <sys/socket.h>
9 #include <sys/types.h>
10 #include <gtest/gtest.h>
11
12 extern "C" {
13 #include "cras_audio_area.h"
14 #include "cras_messages.h"
15 #include "cras_rstream.h"
16 #include "cras_shm.h"
17 }
18
19 namespace {
20
21 class RstreamTestSuite : public testing::Test {
22 protected:
SetUp()23 virtual void SetUp() {
24 int rc;
25 int sock[2] = {-1, -1};
26
27 fmt_.format = SND_PCM_FORMAT_S16_LE;
28 fmt_.frame_rate = 48000;
29 fmt_.num_channels = 2;
30
31 config_.stream_id = 555;
32 config_.stream_type = CRAS_STREAM_TYPE_DEFAULT;
33 config_.direction = CRAS_STREAM_OUTPUT;
34 config_.dev_idx = NO_DEVICE;
35 config_.flags = 0;
36 config_.format = &fmt_;
37 config_.buffer_frames = 4096;
38 config_.cb_threshold = 2048;
39
40 // Create a socket pair because it will be used in rstream.
41 rc = socketpair(AF_UNIX, SOCK_STREAM, 0, sock);
42 ASSERT_EQ(0, rc);
43 config_.audio_fd = sock[1];
44 client_fd_ = sock[0];
45
46 config_.client = NULL;
47 }
48
TearDown()49 virtual void TearDown() {
50 close(config_.audio_fd);
51 close(client_fd_);
52 }
53
format_equal(cras_audio_format * fmt1,cras_audio_format * fmt2)54 static bool format_equal(cras_audio_format *fmt1, cras_audio_format *fmt2) {
55 return fmt1->format == fmt2->format &&
56 fmt1->frame_rate == fmt2->frame_rate &&
57 fmt1->num_channels == fmt2->num_channels;
58 }
59
stub_client_reply(enum CRAS_AUDIO_MESSAGE_ID id,int frames,int err)60 void stub_client_reply(enum CRAS_AUDIO_MESSAGE_ID id, int frames, int err) {
61 int rc;
62 struct audio_message aud_msg;
63 // Create a message.
64 aud_msg.id = id;
65 aud_msg.frames = frames;
66 aud_msg.error = err;
67
68 // Use socket fd to stub message from client.
69 rc = write(client_fd_, &aud_msg, sizeof(aud_msg));
70 EXPECT_EQ(sizeof(aud_msg), rc);
71 return;
72 }
73
74 struct cras_audio_format fmt_;
75 struct cras_rstream_config config_;
76 int client_fd_;
77 };
78
TEST_F(RstreamTestSuite,InvalidDirection)79 TEST_F(RstreamTestSuite, InvalidDirection) {
80 struct cras_rstream *s;
81 int rc;
82
83 config_.direction = (enum CRAS_STREAM_DIRECTION)66;
84 rc = cras_rstream_create(&config_, &s);
85 EXPECT_NE(0, rc);
86 }
87
TEST_F(RstreamTestSuite,InvalidStreamType)88 TEST_F(RstreamTestSuite, InvalidStreamType) {
89 struct cras_rstream *s;
90 int rc;
91
92 config_.stream_type = (enum CRAS_STREAM_TYPE)7;
93 rc = cras_rstream_create(&config_, &s);
94 EXPECT_NE(0, rc);
95 }
96
TEST_F(RstreamTestSuite,InvalidBufferSize)97 TEST_F(RstreamTestSuite, InvalidBufferSize) {
98 struct cras_rstream *s;
99 int rc;
100
101 config_.buffer_frames = 3;
102 rc = cras_rstream_create(&config_, &s);
103 EXPECT_NE(0, rc);
104 }
105
TEST_F(RstreamTestSuite,InvalidCallbackThreshold)106 TEST_F(RstreamTestSuite, InvalidCallbackThreshold) {
107 struct cras_rstream *s;
108 int rc;
109
110 config_.cb_threshold = 3;
111 rc = cras_rstream_create(&config_, &s);
112 EXPECT_NE(0, rc);
113 }
114
TEST_F(RstreamTestSuite,InvalidStreamPointer)115 TEST_F(RstreamTestSuite, InvalidStreamPointer) {
116 int rc;
117
118 rc = cras_rstream_create(&config_, NULL);
119 EXPECT_NE(0, rc);
120 }
121
TEST_F(RstreamTestSuite,CreateOutput)122 TEST_F(RstreamTestSuite, CreateOutput) {
123 struct cras_rstream *s;
124 struct cras_audio_format fmt_ret;
125 struct cras_audio_shm *shm_ret;
126 struct cras_audio_shm shm_mapped;
127 int rc, fd_ret;
128 size_t shm_size;
129
130 rc = cras_rstream_create(&config_, &s);
131 EXPECT_EQ(0, rc);
132 EXPECT_NE((void *)NULL, s);
133 EXPECT_EQ(4096, cras_rstream_get_buffer_frames(s));
134 EXPECT_EQ(2048, cras_rstream_get_cb_threshold(s));
135 EXPECT_EQ(CRAS_STREAM_TYPE_DEFAULT, cras_rstream_get_type(s));
136 EXPECT_EQ(CRAS_STREAM_OUTPUT, cras_rstream_get_direction(s));
137 EXPECT_NE((void *)NULL, cras_rstream_output_shm(s));
138 rc = cras_rstream_get_format(s, &fmt_ret);
139 EXPECT_EQ(0, rc);
140 EXPECT_TRUE(format_equal(&fmt_ret, &fmt_));
141
142 // Check if shm is really set up.
143 shm_ret = cras_rstream_output_shm(s);
144 ASSERT_NE((void *)NULL, shm_ret);
145 fd_ret = cras_rstream_output_shm_fd(s);
146 shm_size = cras_rstream_get_total_shm_size(s);
147 EXPECT_GT(shm_size, 4096);
148 shm_mapped.area = (struct cras_audio_shm_area *)mmap(
149 NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_ret, 0);
150 EXPECT_NE((void *)NULL, shm_mapped.area);
151 cras_shm_copy_shared_config(&shm_mapped);
152 EXPECT_EQ(cras_shm_used_size(&shm_mapped), cras_shm_used_size(shm_ret));
153 munmap(shm_mapped.area, shm_size);
154
155 cras_rstream_destroy(s);
156 }
157
TEST_F(RstreamTestSuite,CreateInput)158 TEST_F(RstreamTestSuite, CreateInput) {
159 struct cras_rstream *s;
160 struct cras_audio_format fmt_ret;
161 struct cras_audio_shm *shm_ret;
162 struct cras_audio_shm shm_mapped;
163 int rc, fd_ret;
164 size_t shm_size;
165
166 config_.direction = CRAS_STREAM_INPUT;
167 rc = cras_rstream_create(&config_, &s);
168 EXPECT_EQ(0, rc);
169 EXPECT_NE((void *)NULL, s);
170 EXPECT_EQ(4096, cras_rstream_get_buffer_frames(s));
171 EXPECT_EQ(2048, cras_rstream_get_cb_threshold(s));
172 EXPECT_EQ(CRAS_STREAM_TYPE_DEFAULT, cras_rstream_get_type(s));
173 EXPECT_EQ(CRAS_STREAM_INPUT, cras_rstream_get_direction(s));
174 EXPECT_NE((void *)NULL, cras_rstream_input_shm(s));
175 rc = cras_rstream_get_format(s, &fmt_ret);
176 EXPECT_EQ(0, rc);
177 EXPECT_TRUE(format_equal(&fmt_ret, &fmt_));
178
179 // Check if shm is really set up.
180 shm_ret = cras_rstream_input_shm(s);
181 ASSERT_NE((void *)NULL, shm_ret);
182 fd_ret = cras_rstream_input_shm_fd(s);
183 shm_size = cras_rstream_get_total_shm_size(s);
184 EXPECT_GT(shm_size, 4096);
185 shm_mapped.area = (struct cras_audio_shm_area *)mmap(
186 NULL, shm_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd_ret, 0);
187 EXPECT_NE((void *)NULL, shm_mapped.area);
188 cras_shm_copy_shared_config(&shm_mapped);
189 EXPECT_EQ(cras_shm_used_size(&shm_mapped), cras_shm_used_size(shm_ret));
190 munmap(shm_mapped.area, shm_size);
191
192 cras_rstream_destroy(s);
193 }
194
TEST_F(RstreamTestSuite,VerifyStreamTypes)195 TEST_F(RstreamTestSuite, VerifyStreamTypes) {
196 struct cras_rstream *s;
197 int rc;
198
199 config_.stream_type = CRAS_STREAM_TYPE_DEFAULT;
200 rc = cras_rstream_create(&config_, &s);
201 EXPECT_EQ(0, rc);
202 EXPECT_EQ(CRAS_STREAM_TYPE_DEFAULT, cras_rstream_get_type(s));
203 EXPECT_NE(CRAS_STREAM_TYPE_MULTIMEDIA, cras_rstream_get_type(s));
204 cras_rstream_destroy(s);
205
206 config_.stream_type = CRAS_STREAM_TYPE_VOICE_COMMUNICATION;
207 rc = cras_rstream_create(&config_, &s);
208 EXPECT_EQ(0, rc);
209 EXPECT_EQ(CRAS_STREAM_TYPE_VOICE_COMMUNICATION, cras_rstream_get_type(s));
210 cras_rstream_destroy(s);
211
212 config_.direction = CRAS_STREAM_INPUT;
213 config_.stream_type = CRAS_STREAM_TYPE_SPEECH_RECOGNITION;
214 rc = cras_rstream_create(&config_, &s);
215 EXPECT_EQ(0, rc);
216 EXPECT_EQ(CRAS_STREAM_TYPE_SPEECH_RECOGNITION, cras_rstream_get_type(s));
217 cras_rstream_destroy(s);
218
219 config_.stream_type = CRAS_STREAM_TYPE_PRO_AUDIO;
220 rc = cras_rstream_create(&config_, &s);
221 EXPECT_EQ(0, rc);
222 EXPECT_EQ(CRAS_STREAM_TYPE_PRO_AUDIO, cras_rstream_get_type(s));
223 cras_rstream_destroy(s);
224 }
225
TEST_F(RstreamTestSuite,OutputStreamIsPendingReply)226 TEST_F(RstreamTestSuite, OutputStreamIsPendingReply) {
227 struct cras_rstream *s;
228 int rc;
229 struct timespec ts;
230
231 rc = cras_rstream_create(&config_, &s);
232 EXPECT_EQ(0, rc);
233
234 // Not pending reply.
235 rc = cras_rstream_is_pending_reply(s);
236 EXPECT_EQ(0, rc);
237
238 // Request some data from client.
239 rc = cras_rstream_request_audio(s, &ts);
240 EXPECT_GT(rc, 0);
241
242 // Pending reply.
243 rc = cras_rstream_is_pending_reply(s);
244 EXPECT_EQ(1, rc);
245
246 cras_rstream_destroy(s);
247 }
248
TEST_F(RstreamTestSuite,OutputStreamFlushMessages)249 TEST_F(RstreamTestSuite, OutputStreamFlushMessages) {
250 struct cras_rstream *s;
251 int rc;
252 struct timespec ts;
253
254 rc = cras_rstream_create(&config_, &s);
255 EXPECT_EQ(0, rc);
256
257 // Not pending reply.
258 rc = cras_rstream_is_pending_reply(s);
259 EXPECT_EQ(0, rc);
260
261 // Request some data from client.
262 rc = cras_rstream_request_audio(s, &ts);
263 EXPECT_GT(rc, 0);
264
265 // Pending reply.
266 rc = cras_rstream_is_pending_reply(s);
267 EXPECT_EQ(1, rc);
268
269 // Client replies that data is ready.
270 stub_client_reply(AUDIO_MESSAGE_DATA_READY, 10, 0);
271
272 // Read messages.
273 cras_rstream_flush_old_audio_messages(s);
274
275 // NOT Pending reply.
276 rc = cras_rstream_is_pending_reply(s);
277 EXPECT_EQ(0, rc);
278
279 cras_rstream_destroy(s);
280 }
281
TEST_F(RstreamTestSuite,InputStreamIsPendingReply)282 TEST_F(RstreamTestSuite, InputStreamIsPendingReply) {
283 struct cras_rstream *s;
284 int rc;
285
286 config_.direction = CRAS_STREAM_INPUT;
287
288 rc = cras_rstream_create(&config_, &s);
289 EXPECT_EQ(0, rc);
290
291 // Not pending reply.
292 rc = cras_rstream_is_pending_reply(s);
293 EXPECT_EQ(0, rc);
294
295 // Some data is ready. Sends it to client.
296 rc = cras_rstream_audio_ready(s, 10);
297 EXPECT_GT(rc, 0);
298
299 // Pending reply.
300 rc = cras_rstream_is_pending_reply(s);
301 EXPECT_EQ(1, rc);
302
303 cras_rstream_destroy(s);
304 }
305
TEST_F(RstreamTestSuite,InputStreamFlushMessages)306 TEST_F(RstreamTestSuite, InputStreamFlushMessages) {
307 struct cras_rstream *s;
308 int rc;
309
310 config_.direction = CRAS_STREAM_INPUT;
311
312 rc = cras_rstream_create(&config_, &s);
313 EXPECT_EQ(0, rc);
314
315 // Not pending reply.
316 rc = cras_rstream_is_pending_reply(s);
317 EXPECT_EQ(0, rc);
318
319 // Some data is ready. Sends it to client.
320 rc = cras_rstream_audio_ready(s, 10);
321 EXPECT_GT(rc, 0);
322
323 // Pending reply.
324 rc = cras_rstream_is_pending_reply(s);
325 EXPECT_EQ(1, rc);
326
327 // Client replies that data is captured.
328 stub_client_reply(AUDIO_MESSAGE_DATA_CAPTURED, 10, 0);
329
330 // Read messages.
331 cras_rstream_flush_old_audio_messages(s);
332
333 // NOT Pending reply.
334 rc = cras_rstream_is_pending_reply(s);
335 EXPECT_EQ(0, rc);
336
337 cras_rstream_destroy(s);
338 }
339
340 } // namespace
341
main(int argc,char ** argv)342 int main(int argc, char **argv) {
343 ::testing::InitGoogleTest(&argc, argv);
344 return RUN_ALL_TESTS();
345 }
346
347 /* stubs */
348 extern "C" {
349
cras_audio_area_create(int num_channels)350 struct cras_audio_area *cras_audio_area_create(int num_channels) {
351 return NULL;
352 }
353
cras_audio_area_destroy(struct cras_audio_area * area)354 void cras_audio_area_destroy(struct cras_audio_area *area) {
355 }
356
cras_audio_area_config_channels(struct cras_audio_area * area,const struct cras_audio_format * fmt)357 void cras_audio_area_config_channels(struct cras_audio_area *area,
358 const struct cras_audio_format *fmt) {
359 }
360
buffer_share_create(unsigned int buf_sz)361 struct buffer_share *buffer_share_create(unsigned int buf_sz) {
362 return NULL;
363 }
364
buffer_share_destroy(struct buffer_share * mix)365 void buffer_share_destroy(struct buffer_share *mix) {
366 }
367
buffer_share_offset_update(struct buffer_share * mix,unsigned int id,unsigned int frames)368 int buffer_share_offset_update(struct buffer_share *mix, unsigned int id,
369 unsigned int frames) {
370 return 0;
371 }
372
buffer_share_get_new_write_point(struct buffer_share * mix)373 unsigned int buffer_share_get_new_write_point(struct buffer_share *mix) {
374 return 0;
375 }
376
buffer_share_add_id(struct buffer_share * mix,unsigned int id)377 int buffer_share_add_id(struct buffer_share *mix, unsigned int id) {
378 return 0;
379 }
380
buffer_share_rm_id(struct buffer_share * mix,unsigned int id)381 int buffer_share_rm_id(struct buffer_share *mix, unsigned int id) {
382 return 0;
383 }
384
buffer_share_id_offset(const struct buffer_share * mix,unsigned int id)385 unsigned int buffer_share_id_offset(const struct buffer_share *mix,
386 unsigned int id)
387 {
388 return 0;
389 }
390
cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction)391 void cras_system_state_stream_added(enum CRAS_STREAM_DIRECTION direction) {
392 }
393
cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction)394 void cras_system_state_stream_removed(enum CRAS_STREAM_DIRECTION direction) {
395 }
396 #ifdef HAVE_WEBRTC_APM
cras_apm_list_create(void * stream_ptr,uint64_t effects)397 struct cras_apm_list *cras_apm_list_create(void *stream_ptr,
398 uint64_t effects)
399 {
400 return NULL;
401 }
cras_apm_list_destroy(struct cras_apm_list * list)402 int cras_apm_list_destroy(struct cras_apm_list *list)
403 {
404 return 0;
405 }
cras_apm_list_get_effects(struct cras_apm_list * list)406 uint64_t cras_apm_list_get_effects(struct cras_apm_list *list)
407 {
408 return APM_ECHO_CANCELLATION;
409 }
cras_apm_list_get(struct cras_apm_list * list,void * dev_ptr)410 struct cras_apm *cras_apm_list_get(struct cras_apm_list *list,
411 void *dev_ptr)
412 {
413 return NULL;
414 }
cras_apm_list_get_format(struct cras_apm * apm)415 struct cras_audio_format *cras_apm_list_get_format(struct cras_apm *apm)
416 {
417 return NULL;
418 }
419 #endif
420 }
421