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