Home | History | Annotate | Download | only in tests
      1 // Copyright (c) 2013 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 <gtest/gtest.h>
      6 #include <vector>
      7 
      8 extern "C" {
      9 // For static function test.
     10 #include "cras_alsa_helpers.c"
     11 }
     12 
     13 static int snd_pcm_sw_params_set_tstamp_type_called;
     14 static int snd_pcm_sw_params_set_tstamp_mode_called;
     15 static snd_pcm_uframes_t snd_pcm_htimestamp_avail_ret_val;
     16 static timespec snd_pcm_htimestamp_tstamp_ret_val;
     17 static std::vector<int> snd_pcm_sw_params_ret_vals;
     18 
     19 static void ResetStubData() {
     20   snd_pcm_sw_params_set_tstamp_type_called = 0;
     21   snd_pcm_sw_params_set_tstamp_mode_called = 0;
     22   snd_pcm_htimestamp_avail_ret_val = 0;
     23   snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 0;
     24   snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 0;
     25   snd_pcm_sw_params_ret_vals.clear();
     26 }
     27 
     28 namespace {
     29 
     30 static snd_pcm_chmap_query_t *create_chmap_cap(snd_pcm_chmap_type type,
     31 					       size_t channels)
     32 {
     33   snd_pcm_chmap_query_t *c;
     34   c = (snd_pcm_chmap_query_t *)calloc(channels + 2, sizeof(int));
     35   c->type = type;
     36   c->map.channels = channels;
     37   return c;
     38 }
     39 
     40 TEST(AlsaHelper, MatchChannelMapCapabilityStereo) {
     41   snd_pcm_chmap_query_t **caps;
     42   snd_pcm_chmap_query_t *c;
     43   struct cras_audio_format *fmt;
     44 
     45   caps = (snd_pcm_chmap_query_t **)calloc(4, sizeof(*caps));
     46 
     47   /* Layout (CRAS_CH_RL, CRAS_CH_RR) corresponds to
     48    * ALSA channel map (5, 6)
     49    */
     50   int8_t channel_layout[CRAS_CH_MAX] =
     51       {-1, -1, 0, 1, -1, -1, -1, -1, -1, -1, -1};
     52 
     53   fmt = cras_audio_format_create(SND_PCM_FORMAT_S16_LE, 44100, 2);
     54   cras_audio_format_set_channel_layout(fmt, channel_layout);
     55 
     56   /* Create a list of capabilities */
     57   c = create_chmap_cap(SND_CHMAP_TYPE_FIXED, 3);
     58   c->map.pos[0] = 3;
     59   c->map.pos[1] = 4;
     60   c->map.pos[2] = 5;
     61   caps[0] = c;
     62 
     63   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
     64   c->map.pos[0] = 5;
     65   c->map.pos[1] = 6;
     66   caps[1] = c;
     67 
     68   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
     69   c->map.pos[0] = 9;
     70   c->map.pos[1] = 10;
     71   caps[2] = c;
     72 
     73   caps[3] = NULL;
     74 
     75   /* Test if there's a cap matches fmt */
     76   c = cras_chmap_caps_match(caps, fmt);
     77   ASSERT_NE((void *)NULL, c);
     78 
     79   caps[1]->map.pos[0] = 5;
     80   caps[1]->map.pos[1] = 7;
     81 
     82   c = cras_chmap_caps_match(caps, fmt);
     83   ASSERT_EQ((void *)NULL, c);
     84 
     85   free(caps[0]);
     86   free(caps[1]);
     87   free(caps[2]);
     88   free(caps[3]);
     89   free(caps);
     90   cras_audio_format_destroy(fmt);
     91 }
     92 
     93 TEST(AlsaHelper, MatchChannelMapCapability51) {
     94   snd_pcm_chmap_query_t **caps = NULL;
     95   snd_pcm_chmap_query_t *c = NULL;
     96   struct cras_audio_format *fmt;
     97 
     98   caps = (snd_pcm_chmap_query_t **)calloc(4, sizeof(*caps));
     99 
    100   /* Layout (CRAS_CH_FL, CRAS_CH_FR, CRAS_CH_RL, CRAS_CH_RR, CRAS_CH_FC)
    101    * corresponds to ALSA channel map (3, 4, 5, 6, 7)
    102    */
    103   int8_t channel_layout[CRAS_CH_MAX] =
    104       {0, 1, 2, 3, 4, 5, -1, -1, -1, -1, -1};
    105 
    106   fmt = cras_audio_format_create(SND_PCM_FORMAT_S16_LE, 44100, 6);
    107   cras_audio_format_set_channel_layout(fmt, channel_layout);
    108 
    109   /* Create a list of capabilities */
    110   c = create_chmap_cap(SND_CHMAP_TYPE_FIXED, 6);
    111   c->map.pos[0] = 3;
    112   c->map.pos[1] = 4;
    113   c->map.pos[2] = 5;
    114   c->map.pos[3] = 6;
    115   c->map.pos[4] = 7;
    116   c->map.pos[5] = 8;
    117   caps[0] = c;
    118 
    119   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 2);
    120   c->map.pos[0] = 6;
    121   c->map.pos[1] = 4;
    122   caps[1] = c;
    123 
    124   c = create_chmap_cap(SND_CHMAP_TYPE_VAR, 6);
    125   c->map.pos[0] = 9;
    126   c->map.pos[1] = 10;
    127   c->map.pos[2] = 5;
    128   c->map.pos[3] = 6;
    129   c->map.pos[4] = 7;
    130   c->map.pos[5] = 8;
    131   caps[2] = c;
    132   caps[3] = NULL;
    133 
    134   /* Test if there's a cap matches fmt */
    135   c = cras_chmap_caps_match(caps, fmt);
    136   ASSERT_NE((void *)NULL, c);
    137 
    138   caps[0]->map.pos[0] = 7;
    139   caps[0]->map.pos[1] = 8;
    140   caps[0]->map.pos[4] = 3;
    141   caps[0]->map.pos[5] = 4;
    142   c = cras_chmap_caps_match(caps, fmt);
    143   ASSERT_EQ((void *)NULL, c);
    144 
    145   caps[0]->type = SND_CHMAP_TYPE_PAIRED;
    146   c = cras_chmap_caps_match(caps, fmt);
    147   ASSERT_NE((void *)NULL, c);
    148 
    149   caps[0]->map.pos[0] = 8;
    150   caps[0]->map.pos[1] = 7;
    151   c = cras_chmap_caps_match(caps, fmt);
    152   ASSERT_EQ((void *)NULL, c);
    153 
    154   caps[0]->type = SND_CHMAP_TYPE_VAR;
    155   c = cras_chmap_caps_match(caps, fmt);
    156   ASSERT_NE((void *)NULL, c);
    157 
    158   free(caps[0]);
    159   free(caps[1]);
    160   free(caps[2]);
    161   free(caps[3]);
    162   free(caps);
    163   cras_audio_format_destroy(fmt);
    164 }
    165 
    166 TEST(AlsaHelper, Htimestamp) {
    167   snd_pcm_t *dummy_handle = reinterpret_cast<snd_pcm_t*>(0x1);
    168   snd_pcm_uframes_t used;
    169   snd_pcm_uframes_t severe_underrun_frames = 480;
    170   struct timespec tstamp;
    171   unsigned int underruns = 0;
    172   int htimestamp_enabled = 1;
    173   const char *dev_name = "dev_name";
    174 
    175   // Enable htimestamp use.
    176   ResetStubData();
    177   EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled));
    178   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 1);
    179   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 1);
    180   EXPECT_EQ(1, htimestamp_enabled);
    181 
    182   // Try to enable htimestamp use: not supported.
    183   ResetStubData();
    184   snd_pcm_sw_params_ret_vals.push_back(-EINVAL);
    185   EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled));
    186   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 2);
    187   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 2);
    188   EXPECT_EQ(0, htimestamp_enabled);
    189 
    190   // Disable htimestamp use.
    191   ResetStubData();
    192   EXPECT_EQ(0, cras_alsa_set_swparams(dummy_handle, &htimestamp_enabled));
    193   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_mode_called, 0);
    194   EXPECT_EQ(snd_pcm_sw_params_set_tstamp_type_called, 0);
    195 
    196   ResetStubData();
    197   tstamp.tv_sec = 0;
    198   tstamp.tv_nsec = 0;
    199   snd_pcm_htimestamp_avail_ret_val = 20000;
    200   snd_pcm_htimestamp_tstamp_ret_val.tv_sec = 10;
    201   snd_pcm_htimestamp_tstamp_ret_val.tv_nsec = 10000;
    202 
    203   cras_alsa_get_avail_frames(dummy_handle, 48000, severe_underrun_frames,
    204                              dev_name, &used, &tstamp, &underruns);
    205   EXPECT_EQ(used, snd_pcm_htimestamp_avail_ret_val);
    206   EXPECT_EQ(tstamp.tv_sec, snd_pcm_htimestamp_tstamp_ret_val.tv_sec);
    207   EXPECT_EQ(tstamp.tv_nsec, snd_pcm_htimestamp_tstamp_ret_val.tv_nsec);
    208 }
    209 
    210 TEST(AlsaHelper, GetAvailFramesSevereUnderrun) {
    211   snd_pcm_t *dummy_handle = reinterpret_cast<snd_pcm_t*>(0x1);
    212   snd_pcm_uframes_t avail;
    213   snd_pcm_uframes_t severe_underrun_frames = 480;
    214   snd_pcm_uframes_t buffer_size = 48000;
    215   struct timespec tstamp;
    216   unsigned int underruns = 0;
    217   int rc;
    218   const char *dev_name = "dev_name";
    219 
    220   ResetStubData();
    221   snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames + 1;
    222   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
    223                                   severe_underrun_frames, dev_name,
    224                                   &avail, &tstamp, &underruns);
    225   // Returns -EPIPE when severe underrun happens.
    226   EXPECT_EQ(rc, -EPIPE);
    227   EXPECT_EQ(1, underruns);
    228 
    229   ResetStubData();
    230   snd_pcm_htimestamp_avail_ret_val = buffer_size + severe_underrun_frames;
    231   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
    232                                   severe_underrun_frames, dev_name,
    233                                   &avail, &tstamp, &underruns);
    234   // Underrun which is not severe enough will be masked.
    235   // avail will be adjusted to buffer_size.
    236   EXPECT_EQ(avail, buffer_size);
    237   EXPECT_EQ(rc, 0);
    238   EXPECT_EQ(2, underruns);
    239 
    240   ResetStubData();
    241   snd_pcm_htimestamp_avail_ret_val = buffer_size;
    242   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
    243                                   severe_underrun_frames, dev_name,
    244                                   &avail, &tstamp, &underruns);
    245   // When avail == buffer_size, num_underruns will be increased.
    246   EXPECT_EQ(avail, buffer_size);
    247   EXPECT_EQ(rc, 0);
    248   EXPECT_EQ(3, underruns);
    249 
    250   ResetStubData();
    251   snd_pcm_htimestamp_avail_ret_val = buffer_size - 1;
    252   rc = cras_alsa_get_avail_frames(dummy_handle, buffer_size,
    253                                   severe_underrun_frames, dev_name,
    254                                   &avail, &tstamp, &underruns);
    255   // When avail < buffer_size, there is no underrun.
    256   EXPECT_EQ(avail, buffer_size - 1);
    257   EXPECT_EQ(rc, 0);
    258   EXPECT_EQ(3, underruns);
    259 }
    260 } // namespace
    261 
    262 extern "C" {
    263 
    264 int snd_pcm_sw_params_current(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) {
    265   return 0;
    266 }
    267 
    268 int snd_pcm_sw_params_get_boundary(const snd_pcm_sw_params_t *params,
    269                                    snd_pcm_uframes_t *val) {
    270   return 0;
    271 }
    272 
    273 int snd_pcm_sw_params_set_stop_threshold(snd_pcm_t *pcm,
    274                                          snd_pcm_sw_params_t *params,
    275                                          snd_pcm_uframes_t val) {
    276   return 0;
    277 }
    278 
    279 int snd_pcm_sw_params_set_start_threshold(snd_pcm_t *pcm,
    280                                           snd_pcm_sw_params_t *params,
    281                                           snd_pcm_uframes_t val) {
    282   return 0;
    283 }
    284 
    285 int snd_pcm_sw_params_set_period_event(snd_pcm_t *pcm,
    286                                        snd_pcm_sw_params_t *params, int val) {
    287   return 0;
    288 }
    289 
    290 int snd_pcm_sw_params_set_tstamp_mode(snd_pcm_t *pcm,
    291                                       snd_pcm_sw_params_t *params,
    292                                       snd_pcm_tstamp_t val) {
    293   snd_pcm_sw_params_set_tstamp_mode_called++;
    294   return 0;
    295 }
    296 
    297 int snd_pcm_sw_params_set_tstamp_type(snd_pcm_t *pcm,
    298                                       snd_pcm_sw_params_t *params,
    299                                       snd_pcm_tstamp_type_t val) {
    300   snd_pcm_sw_params_set_tstamp_type_called++;
    301   return 0;
    302 }
    303 
    304 int snd_pcm_sw_params(snd_pcm_t *pcm, snd_pcm_sw_params_t *params) {
    305   int rc;
    306 
    307   if (snd_pcm_sw_params_ret_vals.size() == 0)
    308     return 0;
    309   rc = snd_pcm_sw_params_ret_vals.back();
    310   snd_pcm_sw_params_ret_vals.pop_back();
    311   return rc;
    312 }
    313 
    314 snd_pcm_sframes_t snd_pcm_avail(snd_pcm_t *pcm) {
    315   return snd_pcm_htimestamp_avail_ret_val;
    316 }
    317 
    318 int snd_pcm_htimestamp(snd_pcm_t *pcm, snd_pcm_uframes_t *avail,
    319                        snd_htimestamp_t *tstamp) {
    320   *avail = snd_pcm_htimestamp_avail_ret_val;
    321   *tstamp = snd_pcm_htimestamp_tstamp_ret_val;
    322   return 0;
    323 }
    324 
    325 }
    326 
    327 int main(int argc, char **argv) {
    328   ::testing::InitGoogleTest(&argc, argv);
    329   return RUN_ALL_TESTS();
    330 }
    331