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 <stdio.h> 6 #include <gtest/gtest.h> 7 8 extern "C" { 9 #include "cras_shm.h" 10 #include "cras_types.h" 11 } 12 13 namespace { 14 15 class ShmTestSuite : public testing::Test{ 16 protected: 17 virtual void SetUp() { 18 memset(&shm_, 0, sizeof(shm_)); 19 shm_.area = 20 static_cast<cras_audio_shm_area *>( 21 calloc(1, sizeof(*shm_.area) + 2048)); 22 cras_shm_set_frame_bytes(&shm_, 4); 23 cras_shm_set_used_size(&shm_, 1024); 24 memcpy(&shm_.area->config, &shm_.config, sizeof(shm_.config)); 25 26 frames_ = 0; 27 } 28 29 virtual void TearDown() { 30 free(shm_.area); 31 } 32 33 struct cras_audio_shm shm_; 34 uint8_t *buf_; 35 size_t frames_; 36 }; 37 38 // Test that and empty buffer returns 0 readable bytes. 39 TEST_F(ShmTestSuite, NoneReadableWhenEmpty) { 40 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 41 EXPECT_EQ(0, frames_); 42 cras_shm_buffer_read(&shm_, frames_); 43 EXPECT_EQ(0, shm_.area->read_offset[0]); 44 } 45 46 // Buffer with 100 frames filled. 47 TEST_F(ShmTestSuite, OneHundredFilled) { 48 shm_.area->write_offset[0] = 100 * shm_.area->config.frame_bytes; 49 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 50 EXPECT_EQ(100, frames_); 51 EXPECT_EQ(shm_.area->samples, buf_); 52 cras_shm_buffer_read(&shm_, frames_ - 9); 53 EXPECT_EQ((frames_ - 9) * shm_.config.frame_bytes, shm_.area->read_offset[0]); 54 cras_shm_buffer_read(&shm_, 9); 55 EXPECT_EQ(0, shm_.area->read_offset[0]); 56 EXPECT_EQ(1, shm_.area->read_buf_idx); 57 } 58 59 // Buffer with 100 frames filled, 50 read. 60 TEST_F(ShmTestSuite, OneHundredFilled50Read) { 61 shm_.area->write_offset[0] = 100 * shm_.config.frame_bytes; 62 shm_.area->read_offset[0] = 50 * shm_.config.frame_bytes; 63 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 64 EXPECT_EQ(50, frames_); 65 EXPECT_EQ((shm_.area->samples + shm_.area->read_offset[0]), buf_); 66 cras_shm_buffer_read(&shm_, frames_ - 10); 67 EXPECT_EQ(shm_.area->write_offset[0] - 10 * shm_.config.frame_bytes, 68 shm_.area->read_offset[0]); 69 cras_shm_buffer_read(&shm_, 10); 70 EXPECT_EQ(0, shm_.area->read_offset[0]); 71 } 72 73 // Buffer with 100 frames filled, 50 read, offset by 25. 74 TEST_F(ShmTestSuite, OneHundredFilled50Read25offset) { 75 shm_.area->write_offset[0] = 100 * shm_.config.frame_bytes; 76 shm_.area->read_offset[0] = 50 * shm_.config.frame_bytes; 77 buf_ = cras_shm_get_readable_frames(&shm_, 25, &frames_); 78 EXPECT_EQ(25, frames_); 79 EXPECT_EQ(shm_.area->samples + shm_.area->read_offset[0] + 80 25 * shm_.area->config.frame_bytes, 81 (uint8_t *)buf_); 82 } 83 84 // Test wrapping across buffers. 85 TEST_F(ShmTestSuite, WrapToNextBuffer) { 86 shm_.config.used_size = 480 * shm_.config.frame_bytes; 87 shm_.area->write_offset[0] = 240 * shm_.config.frame_bytes; 88 shm_.area->read_offset[0] = 120 * shm_.config.frame_bytes; 89 shm_.area->write_offset[1] = 240 * shm_.config.frame_bytes; 90 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 91 EXPECT_EQ(120, frames_); 92 EXPECT_EQ(shm_.area->samples + shm_.area->read_offset[0], (uint8_t *)buf_); 93 buf_ = cras_shm_get_readable_frames(&shm_, frames_, &frames_); 94 EXPECT_EQ(240, frames_); 95 EXPECT_EQ(shm_.area->samples + shm_.config.used_size, (uint8_t *)buf_); 96 cras_shm_buffer_read(&shm_, 350); /* Mark all-10 as read */ 97 EXPECT_EQ(0, shm_.area->read_offset[0]); 98 EXPECT_EQ(230 * shm_.config.frame_bytes, shm_.area->read_offset[1]); 99 } 100 101 // Test wrapping across buffers reading all samples. 102 TEST_F(ShmTestSuite, WrapToNextBufferReadAll) { 103 shm_.config.used_size = 480 * shm_.config.frame_bytes; 104 shm_.area->write_offset[0] = 240 * shm_.config.frame_bytes; 105 shm_.area->read_offset[0] = 120 * shm_.config.frame_bytes; 106 shm_.area->write_offset[1] = 240 * shm_.config.frame_bytes; 107 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 108 EXPECT_EQ(120, frames_); 109 EXPECT_EQ(shm_.area->samples + shm_.area->read_offset[0], (uint8_t *)buf_); 110 buf_ = cras_shm_get_readable_frames(&shm_, frames_, &frames_); 111 EXPECT_EQ(240, frames_); 112 EXPECT_EQ(shm_.area->samples + shm_.config.used_size, (uint8_t *)buf_); 113 cras_shm_buffer_read(&shm_, 360); /* Mark all as read */ 114 EXPECT_EQ(0, shm_.area->read_offset[0]); 115 EXPECT_EQ(0, shm_.area->read_offset[1]); 116 EXPECT_EQ(0, shm_.area->read_buf_idx); 117 } 118 119 // Test wrapping last buffer. 120 TEST_F(ShmTestSuite, WrapFromFinalBuffer) { 121 shm_.area->read_buf_idx = CRAS_NUM_SHM_BUFFERS - 1; 122 shm_.config.used_size = 480 * shm_.config.frame_bytes; 123 shm_.area->write_offset[shm_.area->read_buf_idx] = 124 240 * shm_.config.frame_bytes; 125 shm_.area->read_offset[shm_.area->read_buf_idx] = 126 120 * shm_.config.frame_bytes; 127 shm_.area->write_offset[0] = 240 * shm_.config.frame_bytes; 128 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 129 EXPECT_EQ(120, frames_); 130 EXPECT_EQ((uint8_t *)buf_, shm_.area->samples + 131 shm_.config.used_size * shm_.area->read_buf_idx + 132 shm_.area->read_offset[shm_.area->read_buf_idx]); 133 buf_ = cras_shm_get_readable_frames(&shm_, frames_, &frames_); 134 EXPECT_EQ(240, frames_); 135 EXPECT_EQ(shm_.area->samples, (uint8_t *)buf_); 136 cras_shm_buffer_read(&shm_, 350); /* Mark all-10 as read */ 137 EXPECT_EQ(0, shm_.area->read_offset[1]); 138 EXPECT_EQ(230 * shm_.config.frame_bytes, shm_.area->read_offset[0]); 139 } 140 141 // Test Check available to write returns 0 if not free buffer. 142 TEST_F(ShmTestSuite, WriteAvailNotFree) { 143 size_t ret; 144 shm_.area->write_buf_idx = 0; 145 shm_.area->write_offset[0] = 100 * shm_.config.frame_bytes; 146 shm_.area->read_offset[0] = 50 * shm_.config.frame_bytes; 147 ret = cras_shm_get_num_writeable(&shm_); 148 EXPECT_EQ(0, ret); 149 } 150 151 // Test Check available to write returns num_frames if free buffer. 152 TEST_F(ShmTestSuite, WriteAvailValid) { 153 size_t ret; 154 shm_.area->write_buf_idx = 0; 155 shm_.config.used_size = 480 * shm_.config.frame_bytes; 156 shm_.area->write_offset[0] = 0; 157 shm_.area->read_offset[0] = 0; 158 ret = cras_shm_get_num_writeable(&shm_); 159 EXPECT_EQ(480, ret); 160 } 161 162 // Test get frames_written returns the number of frames written. 163 TEST_F(ShmTestSuite, GetNumWritten) { 164 size_t ret; 165 shm_.area->write_buf_idx = 0; 166 shm_.config.used_size = 480 * shm_.config.frame_bytes; 167 shm_.area->write_offset[0] = 200 * shm_.config.frame_bytes; 168 shm_.area->read_offset[0] = 0; 169 ret = cras_shm_frames_written(&shm_); 170 EXPECT_EQ(200, ret); 171 } 172 173 // Test that getting the base of the write buffer returns the correct pointer. 174 TEST_F(ShmTestSuite, GetWriteBufferBase) { 175 uint8_t* ret; 176 177 shm_.area->write_buf_idx = 0; 178 shm_.config.used_size = 480 * shm_.config.frame_bytes; 179 shm_.area->write_offset[0] = 200 * shm_.config.frame_bytes; 180 shm_.area->write_offset[1] = 200 * shm_.config.frame_bytes; 181 shm_.area->read_offset[0] = 0; 182 shm_.area->read_offset[1] = 0; 183 ret = cras_shm_get_write_buffer_base(&shm_); 184 EXPECT_EQ(shm_.area->samples, ret); 185 186 shm_.area->write_buf_idx = 1; 187 ret = cras_shm_get_write_buffer_base(&shm_); 188 EXPECT_EQ(shm_.area->samples + shm_.config.used_size, ret); 189 } 190 191 TEST_F(ShmTestSuite, SetVolume) { 192 cras_shm_set_volume_scaler(&shm_, 1.0); 193 EXPECT_EQ(shm_.area->volume_scaler, 1.0); 194 cras_shm_set_volume_scaler(&shm_, 1.4); 195 EXPECT_EQ(shm_.area->volume_scaler, 1.0); 196 cras_shm_set_volume_scaler(&shm_, -0.5); 197 EXPECT_EQ(shm_.area->volume_scaler, 0.0); 198 cras_shm_set_volume_scaler(&shm_, 0.5); 199 EXPECT_EQ(shm_.area->volume_scaler, 0.5); 200 } 201 202 // Test that invalid read/write offsets are detected. 203 204 TEST_F(ShmTestSuite, InvalidWriteOffset) { 205 shm_.area->write_offset[0] = shm_.config.used_size + 50; 206 shm_.area->read_offset[0] = 0; 207 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 208 EXPECT_EQ(shm_.config.used_size / 4, frames_); 209 } 210 211 TEST_F(ShmTestSuite, InvalidReadOffset) { 212 // Should ignore read+_offset and assume 0. 213 shm_.area->write_offset[0] = 44; 214 shm_.area->read_offset[0] = shm_.config.used_size + 25; 215 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 216 EXPECT_EQ(shm_.area->write_offset[0] / shm_.config.frame_bytes, frames_); 217 EXPECT_EQ(shm_.area->samples, (uint8_t *)buf_); 218 } 219 220 TEST_F(ShmTestSuite, InvalidReadAndWriteOffset) { 221 shm_.area->write_offset[0] = shm_.config.used_size + 50; 222 shm_.area->read_offset[0] = shm_.config.used_size + 25; 223 buf_ = cras_shm_get_readable_frames(&shm_, 0, &frames_); 224 EXPECT_EQ(shm_.config.used_size / 4, frames_); 225 } 226 227 TEST_F(ShmTestSuite, InputBufferOverrun) { 228 int rc; 229 shm_.area->write_offset[0] = 0; 230 shm_.area->read_offset[0] = 0; 231 shm_.area->write_offset[1] = 0; 232 shm_.area->read_offset[1] = 0; 233 234 shm_.area->write_buf_idx = 0; 235 shm_.area->read_buf_idx = 0; 236 237 EXPECT_EQ(0, cras_shm_num_overruns(&shm_)); 238 rc = cras_shm_check_write_overrun(&shm_); 239 EXPECT_EQ(0, rc); 240 cras_shm_buffer_written(&shm_, 100); 241 cras_shm_buffer_write_complete(&shm_); 242 243 rc = cras_shm_check_write_overrun(&shm_); 244 EXPECT_EQ(0, rc); 245 cras_shm_buffer_written(&shm_, 100); 246 cras_shm_buffer_write_complete(&shm_); 247 248 // Assert two consecutive writes causes overrun. 249 rc = cras_shm_check_write_overrun(&shm_); 250 EXPECT_EQ(1, rc); 251 EXPECT_EQ(1, cras_shm_num_overruns(&shm_)); 252 } 253 254 TEST_F(ShmTestSuite, GetWritableFramesNeedToWrite) { 255 unsigned buffer_size = 480; 256 unsigned limit = 480; 257 unsigned written = 200; 258 unsigned frames; 259 shm_.area->write_buf_idx = 0; 260 shm_.config.used_size = buffer_size * shm_.config.frame_bytes; 261 shm_.area->write_offset[0] = written * shm_.config.frame_bytes; 262 buf_ = cras_shm_get_writeable_frames(&shm_, limit, &frames); 263 EXPECT_EQ(limit - written, frames); 264 EXPECT_EQ(shm_.area->samples + shm_.area->write_offset[0], buf_); 265 } 266 267 TEST_F(ShmTestSuite, GetWritableFramesNoNeedToWrite) { 268 unsigned buffer_size = 480; 269 unsigned limit = 240; 270 unsigned written = 300; 271 unsigned frames; 272 shm_.area->write_buf_idx = 0; 273 shm_.config.used_size = buffer_size * shm_.config.frame_bytes; 274 shm_.area->write_offset[0] = written * shm_.config.frame_bytes; 275 buf_ = cras_shm_get_writeable_frames(&shm_, limit, &frames); 276 EXPECT_EQ(0, frames); 277 EXPECT_EQ(shm_.area->samples + shm_.area->write_offset[0], buf_); 278 } 279 280 } // namespace 281 282 int main(int argc, char **argv) { 283 ::testing::InitGoogleTest(&argc, argv); 284 return RUN_ALL_TESTS(); 285 } 286