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