[MemSheriff] More sendto parameter issues.
[chromium-blink-merge.git] / media / audio / alsa / alsa_output_unittest.cc
bloba68be4bbd0c35281cbfc30ffbbdc0437e5445998
1 // Copyright 2013 The Chromium 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.
5 #include "base/strings/stringprintf.h"
6 #include "media/audio/alsa/alsa_output.h"
7 #include "media/audio/alsa/alsa_wrapper.h"
8 #include "media/audio/alsa/audio_manager_alsa.h"
9 #include "media/audio/fake_audio_log_factory.h"
10 #include "media/audio/mock_audio_source_callback.h"
11 #include "media/base/data_buffer.h"
12 #include "media/base/seekable_buffer.h"
13 #include "testing/gmock/include/gmock/gmock.h"
14 #include "testing/gtest/include/gtest/gtest.h"
16 using testing::_;
17 using testing::AllOf;
18 using testing::AtLeast;
19 using testing::DoAll;
20 using testing::Field;
21 using testing::InSequence;
22 using testing::Invoke;
23 using testing::InvokeWithoutArgs;
24 using testing::Mock;
25 using testing::MockFunction;
26 using testing::Return;
27 using testing::SetArgumentPointee;
28 using testing::StrictMock;
29 using testing::StrEq;
30 using testing::Unused;
32 namespace media {
34 class MockAlsaWrapper : public AlsaWrapper {
35 public:
36 MOCK_METHOD3(DeviceNameHint, int(int card,
37 const char* iface,
38 void*** hints));
39 MOCK_METHOD2(DeviceNameGetHint, char*(const void* hint, const char* id));
40 MOCK_METHOD1(DeviceNameFreeHint, int(void** hints));
42 MOCK_METHOD4(PcmOpen, int(snd_pcm_t** handle, const char* name,
43 snd_pcm_stream_t stream, int mode));
44 MOCK_METHOD1(PcmClose, int(snd_pcm_t* handle));
45 MOCK_METHOD1(PcmPrepare, int(snd_pcm_t* handle));
46 MOCK_METHOD1(PcmDrop, int(snd_pcm_t* handle));
47 MOCK_METHOD2(PcmDelay, int(snd_pcm_t* handle, snd_pcm_sframes_t* delay));
48 MOCK_METHOD3(PcmWritei, snd_pcm_sframes_t(snd_pcm_t* handle,
49 const void* buffer,
50 snd_pcm_uframes_t size));
51 MOCK_METHOD3(PcmReadi, snd_pcm_sframes_t(snd_pcm_t* handle,
52 void* buffer,
53 snd_pcm_uframes_t size));
54 MOCK_METHOD3(PcmRecover, int(snd_pcm_t* handle, int err, int silent));
55 MOCK_METHOD7(PcmSetParams, int(snd_pcm_t* handle, snd_pcm_format_t format,
56 snd_pcm_access_t access, unsigned int channels,
57 unsigned int rate, int soft_resample,
58 unsigned int latency));
59 MOCK_METHOD3(PcmGetParams, int(snd_pcm_t* handle,
60 snd_pcm_uframes_t* buffer_size,
61 snd_pcm_uframes_t* period_size));
62 MOCK_METHOD1(PcmName, const char*(snd_pcm_t* handle));
63 MOCK_METHOD1(PcmAvailUpdate, snd_pcm_sframes_t(snd_pcm_t* handle));
64 MOCK_METHOD1(PcmState, snd_pcm_state_t(snd_pcm_t* handle));
65 MOCK_METHOD1(PcmStart, int(snd_pcm_t* handle));
67 MOCK_METHOD1(StrError, const char*(int errnum));
70 class MockAudioManagerAlsa : public AudioManagerAlsa {
71 public:
72 MockAudioManagerAlsa() : AudioManagerAlsa(&fake_audio_log_factory_) {}
73 MOCK_METHOD0(Init, void());
74 MOCK_METHOD0(HasAudioOutputDevices, bool());
75 MOCK_METHOD0(HasAudioInputDevices, bool());
76 MOCK_METHOD1(MakeLinearOutputStream, AudioOutputStream*(
77 const AudioParameters& params));
78 MOCK_METHOD2(MakeLowLatencyOutputStream, AudioOutputStream*(
79 const AudioParameters& params,
80 const std::string& device_id));
81 MOCK_METHOD2(MakeLowLatencyInputStream, AudioInputStream*(
82 const AudioParameters& params, const std::string& device_id));
84 // We need to override this function in order to skip the checking the number
85 // of active output streams. It is because the number of active streams
86 // is managed inside MakeAudioOutputStream, and we don't use
87 // MakeAudioOutputStream to create the stream in the tests.
88 virtual void ReleaseOutputStream(AudioOutputStream* stream) override {
89 DCHECK(stream);
90 delete stream;
93 // We don't mock this method since all tests will do the same thing
94 // and use the current task runner.
95 virtual scoped_refptr<base::SingleThreadTaskRunner> GetTaskRunner() override {
96 return base::MessageLoop::current()->message_loop_proxy();
99 private:
100 FakeAudioLogFactory fake_audio_log_factory_;
103 class AlsaPcmOutputStreamTest : public testing::Test {
104 protected:
105 AlsaPcmOutputStreamTest() {
106 mock_manager_.reset(new StrictMock<MockAudioManagerAlsa>());
109 virtual ~AlsaPcmOutputStreamTest() {
112 AlsaPcmOutputStream* CreateStream(ChannelLayout layout) {
113 return CreateStream(layout, kTestFramesPerPacket);
116 AlsaPcmOutputStream* CreateStream(ChannelLayout layout,
117 int32 samples_per_packet) {
118 AudioParameters params(kTestFormat, layout, kTestSampleRate,
119 kTestBitsPerSample, samples_per_packet);
120 return new AlsaPcmOutputStream(kTestDeviceName,
121 params,
122 &mock_alsa_wrapper_,
123 mock_manager_.get());
126 // Helper function to malloc the string returned by DeviceNameHint for NAME.
127 static char* EchoHint(const void* name, Unused) {
128 return strdup(static_cast<const char*>(name));
131 // Helper function to malloc the string returned by DeviceNameHint for IOID.
132 static char* OutputHint(Unused, Unused) {
133 return strdup("Output");
136 // Helper function to initialize |test_stream->buffer_|. Must be called
137 // in all tests that use buffer_ without opening the stream.
138 void InitBuffer(AlsaPcmOutputStream* test_stream) {
139 DCHECK(test_stream);
140 packet_ = new media::DataBuffer(kTestPacketSize);
141 packet_->set_data_size(kTestPacketSize);
142 test_stream->buffer_.reset(new media::SeekableBuffer(0, kTestPacketSize));
143 test_stream->buffer_->Append(packet_.get());
146 static const ChannelLayout kTestChannelLayout;
147 static const int kTestSampleRate;
148 static const int kTestBitsPerSample;
149 static const int kTestBytesPerFrame;
150 static const AudioParameters::Format kTestFormat;
151 static const char kTestDeviceName[];
152 static const char kDummyMessage[];
153 static const uint32 kTestFramesPerPacket;
154 static const int kTestPacketSize;
155 static const int kTestFailedErrno;
156 static snd_pcm_t* const kFakeHandle;
158 // Used to simulate DeviceNameHint.
159 static char kSurround40[];
160 static char kSurround41[];
161 static char kSurround50[];
162 static char kSurround51[];
163 static char kSurround70[];
164 static char kSurround71[];
165 static void* kFakeHints[];
167 StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
168 scoped_ptr<StrictMock<MockAudioManagerAlsa> > mock_manager_;
169 base::MessageLoop message_loop_;
170 scoped_refptr<media::DataBuffer> packet_;
172 private:
173 DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStreamTest);
176 const ChannelLayout AlsaPcmOutputStreamTest::kTestChannelLayout =
177 CHANNEL_LAYOUT_STEREO;
178 const int AlsaPcmOutputStreamTest::kTestSampleRate =
179 AudioParameters::kAudioCDSampleRate;
180 const int AlsaPcmOutputStreamTest::kTestBitsPerSample = 8;
181 const int AlsaPcmOutputStreamTest::kTestBytesPerFrame =
182 AlsaPcmOutputStreamTest::kTestBitsPerSample / 8 *
183 ChannelLayoutToChannelCount(AlsaPcmOutputStreamTest::kTestChannelLayout);
184 const AudioParameters::Format AlsaPcmOutputStreamTest::kTestFormat =
185 AudioParameters::AUDIO_PCM_LINEAR;
186 const char AlsaPcmOutputStreamTest::kTestDeviceName[] = "TestDevice";
187 const char AlsaPcmOutputStreamTest::kDummyMessage[] = "dummy";
188 const uint32 AlsaPcmOutputStreamTest::kTestFramesPerPacket = 1000;
189 const int AlsaPcmOutputStreamTest::kTestPacketSize =
190 AlsaPcmOutputStreamTest::kTestFramesPerPacket *
191 AlsaPcmOutputStreamTest::kTestBytesPerFrame;
192 const int AlsaPcmOutputStreamTest::kTestFailedErrno = -EACCES;
193 snd_pcm_t* const AlsaPcmOutputStreamTest::kFakeHandle =
194 reinterpret_cast<snd_pcm_t*>(1);
196 char AlsaPcmOutputStreamTest::kSurround40[] = "surround40:CARD=foo,DEV=0";
197 char AlsaPcmOutputStreamTest::kSurround41[] = "surround41:CARD=foo,DEV=0";
198 char AlsaPcmOutputStreamTest::kSurround50[] = "surround50:CARD=foo,DEV=0";
199 char AlsaPcmOutputStreamTest::kSurround51[] = "surround51:CARD=foo,DEV=0";
200 char AlsaPcmOutputStreamTest::kSurround70[] = "surround70:CARD=foo,DEV=0";
201 char AlsaPcmOutputStreamTest::kSurround71[] = "surround71:CARD=foo,DEV=0";
202 void* AlsaPcmOutputStreamTest::kFakeHints[] = {
203 kSurround40, kSurround41, kSurround50, kSurround51,
204 kSurround70, kSurround71, NULL };
206 // Custom action to clear a memory buffer.
207 ACTION(ClearBuffer) {
208 arg0->Zero();
211 TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
212 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
213 EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
214 test_stream->Close();
216 // Should support mono.
217 test_stream = CreateStream(CHANNEL_LAYOUT_MONO);
218 EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
219 test_stream->Close();
221 // Should support multi-channel.
222 test_stream = CreateStream(CHANNEL_LAYOUT_SURROUND);
223 EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
224 test_stream->Close();
226 // Bad bits per sample.
227 AudioParameters bad_bps_params(kTestFormat, kTestChannelLayout,
228 kTestSampleRate, kTestBitsPerSample - 1,
229 kTestFramesPerPacket);
230 test_stream = new AlsaPcmOutputStream(kTestDeviceName,
231 bad_bps_params,
232 &mock_alsa_wrapper_,
233 mock_manager_.get());
234 EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
235 test_stream->Close();
237 // Bad format.
238 AudioParameters bad_format_params(
239 AudioParameters::AUDIO_LAST_FORMAT, kTestChannelLayout, kTestSampleRate,
240 kTestBitsPerSample, kTestFramesPerPacket);
241 test_stream = new AlsaPcmOutputStream(kTestDeviceName,
242 bad_format_params,
243 &mock_alsa_wrapper_,
244 mock_manager_.get());
245 EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
246 test_stream->Close();
249 TEST_F(AlsaPcmOutputStreamTest, LatencyFloor) {
250 const double kMicrosPerFrame =
251 static_cast<double>(1000000) / kTestSampleRate;
252 const double kPacketFramesInMinLatency =
253 AlsaPcmOutputStream::kMinLatencyMicros / kMicrosPerFrame / 2.0;
255 // Test that packets which would cause a latency under less than
256 // AlsaPcmOutputStream::kMinLatencyMicros will get clipped to
257 // AlsaPcmOutputStream::kMinLatencyMicros,
258 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
259 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
260 Return(0)));
261 EXPECT_CALL(mock_alsa_wrapper_,
262 PcmSetParams(_, _, _, _, _, _,
263 AlsaPcmOutputStream::kMinLatencyMicros))
264 .WillOnce(Return(0));
265 EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
266 .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
267 SetArgumentPointee<2>(kTestFramesPerPacket / 2),
268 Return(0)));
270 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout,
271 kPacketFramesInMinLatency);
272 ASSERT_TRUE(test_stream->Open());
274 // Now close it and test that everything was released.
275 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle)).WillOnce(Return(0));
276 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
277 .WillOnce(Return(kTestDeviceName));
278 test_stream->Close();
280 Mock::VerifyAndClear(&mock_alsa_wrapper_);
281 Mock::VerifyAndClear(mock_manager_.get());
283 // Test that having more packets ends up with a latency based on packet size.
284 const int kOverMinLatencyPacketSize = kPacketFramesInMinLatency + 1;
285 int64 expected_micros = AlsaPcmOutputStream::FramesToTimeDelta(
286 kOverMinLatencyPacketSize * 2, kTestSampleRate).InMicroseconds();
288 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
289 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
290 EXPECT_CALL(mock_alsa_wrapper_,
291 PcmSetParams(_, _, _, _, _, _, expected_micros))
292 .WillOnce(Return(0));
293 EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
294 .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
295 SetArgumentPointee<2>(kTestFramesPerPacket / 2),
296 Return(0)));
298 test_stream = CreateStream(kTestChannelLayout,
299 kOverMinLatencyPacketSize);
300 ASSERT_TRUE(test_stream->Open());
302 // Now close it and test that everything was released.
303 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
304 .WillOnce(Return(0));
305 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
306 .WillOnce(Return(kTestDeviceName));
307 test_stream->Close();
309 Mock::VerifyAndClear(&mock_alsa_wrapper_);
310 Mock::VerifyAndClear(mock_manager_.get());
313 TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
314 int64 expected_micros = AlsaPcmOutputStream::FramesToTimeDelta(
315 2 * kTestFramesPerPacket, kTestSampleRate).InMicroseconds();
317 // Open() call opens the playback device, sets the parameters, posts a task
318 // with the resulting configuration data, and transitions the object state to
319 // kIsOpened.
320 EXPECT_CALL(mock_alsa_wrapper_,
321 PcmOpen(_, StrEq(kTestDeviceName),
322 SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK))
323 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
324 Return(0)));
325 EXPECT_CALL(mock_alsa_wrapper_,
326 PcmSetParams(kFakeHandle,
327 SND_PCM_FORMAT_U8,
328 SND_PCM_ACCESS_RW_INTERLEAVED,
329 ChannelLayoutToChannelCount(kTestChannelLayout),
330 kTestSampleRate,
332 expected_micros))
333 .WillOnce(Return(0));
334 EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(kFakeHandle, _, _))
335 .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
336 SetArgumentPointee<2>(kTestFramesPerPacket / 2),
337 Return(0)));
339 // Open the stream.
340 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
341 ASSERT_TRUE(test_stream->Open());
343 EXPECT_EQ(AlsaPcmOutputStream::kIsOpened, test_stream->state());
344 EXPECT_EQ(kFakeHandle, test_stream->playback_handle_);
345 EXPECT_EQ(kTestFramesPerPacket, test_stream->frames_per_packet_);
346 EXPECT_TRUE(test_stream->buffer_.get());
347 EXPECT_FALSE(test_stream->stop_stream_);
349 // Now close it and test that everything was released.
350 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
351 .WillOnce(Return(0));
352 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
353 .WillOnce(Return(kTestDeviceName));
354 test_stream->Close();
357 TEST_F(AlsaPcmOutputStreamTest, PcmOpenFailed) {
358 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
359 .WillOnce(Return(kTestFailedErrno));
360 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
361 .WillOnce(Return(kDummyMessage));
363 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
364 ASSERT_FALSE(test_stream->Open());
365 ASSERT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
367 // Ensure internal state is set for a no-op stream if PcmOpen() failes.
368 EXPECT_TRUE(test_stream->stop_stream_);
369 EXPECT_TRUE(test_stream->playback_handle_ == NULL);
370 EXPECT_FALSE(test_stream->buffer_.get());
372 // Close the stream since we opened it to make destruction happy.
373 test_stream->Close();
376 TEST_F(AlsaPcmOutputStreamTest, PcmSetParamsFailed) {
377 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
378 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
379 Return(0)));
380 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
381 .WillOnce(Return(kTestFailedErrno));
382 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
383 .WillOnce(Return(0));
384 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
385 .WillOnce(Return(kTestDeviceName));
386 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
387 .WillOnce(Return(kDummyMessage));
389 // If open fails, the stream stays in kCreated because it has effectively had
390 // no changes.
391 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
392 ASSERT_FALSE(test_stream->Open());
393 EXPECT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
395 // Ensure internal state is set for a no-op stream if PcmSetParams() failes.
396 EXPECT_TRUE(test_stream->stop_stream_);
397 EXPECT_TRUE(test_stream->playback_handle_ == NULL);
398 EXPECT_FALSE(test_stream->buffer_.get());
400 // Close the stream since we opened it to make destruction happy.
401 test_stream->Close();
404 TEST_F(AlsaPcmOutputStreamTest, StartStop) {
405 // Open() call opens the playback device, sets the parameters, posts a task
406 // with the resulting configuration data, and transitions the object state to
407 // kIsOpened.
408 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
409 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
410 Return(0)));
411 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
412 .WillOnce(Return(0));
413 EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
414 .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
415 SetArgumentPointee<2>(kTestFramesPerPacket / 2),
416 Return(0)));
418 // Open the stream.
419 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
420 ASSERT_TRUE(test_stream->Open());
422 // Expect Device setup.
423 EXPECT_CALL(mock_alsa_wrapper_, PcmDrop(kFakeHandle))
424 .WillOnce(Return(0));
425 EXPECT_CALL(mock_alsa_wrapper_, PcmPrepare(kFakeHandle))
426 .WillOnce(Return(0));
428 // Expect the pre-roll.
429 MockAudioSourceCallback mock_callback;
430 EXPECT_CALL(mock_alsa_wrapper_, PcmState(kFakeHandle))
431 .WillRepeatedly(Return(SND_PCM_STATE_RUNNING));
432 EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(kFakeHandle, _))
433 .WillRepeatedly(DoAll(SetArgumentPointee<1>(0), Return(0)));
434 EXPECT_CALL(mock_callback, OnMoreData(_, _))
435 .WillRepeatedly(DoAll(ClearBuffer(), Return(kTestFramesPerPacket)));
436 EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
437 .WillRepeatedly(Return(kTestFramesPerPacket));
439 // Expect scheduling.
440 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
441 .Times(AtLeast(2))
442 .WillRepeatedly(Return(kTestFramesPerPacket));
444 test_stream->Start(&mock_callback);
445 // Start() will issue a WriteTask() directly and then schedule the next one,
446 // call Stop() immediately after to ensure we don't run the message loop
447 // forever.
448 test_stream->Stop();
449 message_loop_.RunUntilIdle();
451 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
452 .WillOnce(Return(0));
453 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
454 .WillOnce(Return(kTestDeviceName));
455 test_stream->Close();
458 TEST_F(AlsaPcmOutputStreamTest, WritePacket_FinishedPacket) {
459 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
460 InitBuffer(test_stream);
461 test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
462 test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
464 // Nothing should happen. Don't set any expectations and Our strict mocks
465 // should verify most of this.
467 // Test empty buffer.
468 test_stream->buffer_->Clear();
469 test_stream->WritePacket();
470 test_stream->Close();
473 TEST_F(AlsaPcmOutputStreamTest, WritePacket_NormalPacket) {
474 // We need to open the stream before writing data to ALSA.
475 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
476 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
477 Return(0)));
478 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
479 .WillOnce(Return(0));
480 EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
481 .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
482 SetArgumentPointee<2>(kTestFramesPerPacket / 2),
483 Return(0)));
484 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
485 ASSERT_TRUE(test_stream->Open());
486 InitBuffer(test_stream);
487 test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
489 // Write a little less than half the data.
490 int written = packet_->data_size() / kTestBytesPerFrame / 2 - 1;
491 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
492 .WillOnce(Return(written));
493 EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, packet_->data(), _))
494 .WillOnce(Return(written));
496 test_stream->WritePacket();
498 ASSERT_EQ(test_stream->buffer_->forward_bytes(),
499 packet_->data_size() - written * kTestBytesPerFrame);
501 // Write the rest.
502 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
503 .WillOnce(Return(kTestFramesPerPacket - written));
504 EXPECT_CALL(mock_alsa_wrapper_,
505 PcmWritei(kFakeHandle,
506 packet_->data() + written * kTestBytesPerFrame,
508 .WillOnce(Return(packet_->data_size() / kTestBytesPerFrame - written));
509 test_stream->WritePacket();
510 EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
512 // Now close it and test that everything was released.
513 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
514 .WillOnce(Return(0));
515 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
516 .WillOnce(Return(kTestDeviceName));
517 test_stream->Close();
520 TEST_F(AlsaPcmOutputStreamTest, WritePacket_WriteFails) {
521 // We need to open the stream before writing data to ALSA.
522 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, _, _, _))
523 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle),
524 Return(0)));
525 EXPECT_CALL(mock_alsa_wrapper_, PcmSetParams(_, _, _, _, _, _, _))
526 .WillOnce(Return(0));
527 EXPECT_CALL(mock_alsa_wrapper_, PcmGetParams(_, _, _))
528 .WillOnce(DoAll(SetArgumentPointee<1>(kTestFramesPerPacket),
529 SetArgumentPointee<2>(kTestFramesPerPacket / 2),
530 Return(0)));
531 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
532 ASSERT_TRUE(test_stream->Open());
533 InitBuffer(test_stream);
534 test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
536 // Fail due to a recoverable error and see that PcmRecover code path
537 // continues normally.
538 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
539 .WillOnce(Return(kTestFramesPerPacket));
540 EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
541 .WillOnce(Return(-EINTR));
542 EXPECT_CALL(mock_alsa_wrapper_, PcmRecover(kFakeHandle, _, _))
543 .WillOnce(Return(0));
545 test_stream->WritePacket();
547 ASSERT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
549 // Fail the next write, and see that stop_stream_ is set.
550 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
551 .WillOnce(Return(kTestFramesPerPacket));
552 EXPECT_CALL(mock_alsa_wrapper_, PcmWritei(kFakeHandle, _, _))
553 .WillOnce(Return(kTestFailedErrno));
554 EXPECT_CALL(mock_alsa_wrapper_, PcmRecover(kFakeHandle, _, _))
555 .WillOnce(Return(kTestFailedErrno));
556 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
557 .WillOnce(Return(kDummyMessage));
558 test_stream->WritePacket();
559 EXPECT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
560 EXPECT_TRUE(test_stream->stop_stream_);
562 // Now close it and test that everything was released.
563 EXPECT_CALL(mock_alsa_wrapper_, PcmClose(kFakeHandle))
564 .WillOnce(Return(0));
565 EXPECT_CALL(mock_alsa_wrapper_, PcmName(kFakeHandle))
566 .WillOnce(Return(kTestDeviceName));
567 test_stream->Close();
570 TEST_F(AlsaPcmOutputStreamTest, WritePacket_StopStream) {
571 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
572 InitBuffer(test_stream);
573 test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
574 test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
576 // No expectations set on the strict mock because nothing should be called.
577 test_stream->stop_stream_ = true;
578 test_stream->WritePacket();
579 EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
580 test_stream->Close();
583 TEST_F(AlsaPcmOutputStreamTest, BufferPacket) {
584 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
585 InitBuffer(test_stream);
586 test_stream->buffer_->Clear();
588 MockAudioSourceCallback mock_callback;
589 EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
590 .WillOnce(Return(SND_PCM_STATE_RUNNING));
591 EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _))
592 .WillOnce(DoAll(SetArgumentPointee<1>(1), Return(0)));
593 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
594 .WillRepeatedly(Return(0)); // Buffer is full.
596 // Return a partially filled packet.
597 EXPECT_CALL(mock_callback, OnMoreData(_, _))
598 .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
600 bool source_exhausted;
601 test_stream->set_source_callback(&mock_callback);
602 test_stream->packet_size_ = kTestPacketSize;
603 test_stream->BufferPacket(&source_exhausted);
605 EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
606 EXPECT_FALSE(source_exhausted);
607 test_stream->Close();
610 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Negative) {
611 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
612 InitBuffer(test_stream);
613 test_stream->buffer_->Clear();
615 // Simulate where the underrun has occurred right after checking the delay.
616 MockAudioSourceCallback mock_callback;
617 EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
618 .WillOnce(Return(SND_PCM_STATE_RUNNING));
619 EXPECT_CALL(mock_alsa_wrapper_, PcmDelay(_, _))
620 .WillOnce(DoAll(SetArgumentPointee<1>(-1), Return(0)));
621 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
622 .WillRepeatedly(Return(0)); // Buffer is full.
623 EXPECT_CALL(mock_callback, OnMoreData(_, _))
624 .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
626 bool source_exhausted;
627 test_stream->set_source_callback(&mock_callback);
628 test_stream->packet_size_ = kTestPacketSize;
629 test_stream->BufferPacket(&source_exhausted);
631 EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
632 EXPECT_FALSE(source_exhausted);
633 test_stream->Close();
636 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Underrun) {
637 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
638 InitBuffer(test_stream);
639 test_stream->buffer_->Clear();
641 // If ALSA has underrun then we should assume a delay of zero.
642 MockAudioSourceCallback mock_callback;
643 EXPECT_CALL(mock_alsa_wrapper_, PcmState(_))
644 .WillOnce(Return(SND_PCM_STATE_XRUN));
645 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
646 .WillRepeatedly(Return(0)); // Buffer is full.
647 EXPECT_CALL(mock_callback, OnMoreData(_, 0))
648 .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
650 bool source_exhausted;
651 test_stream->set_source_callback(&mock_callback);
652 test_stream->packet_size_ = kTestPacketSize;
653 test_stream->BufferPacket(&source_exhausted);
655 EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
656 EXPECT_FALSE(source_exhausted);
657 test_stream->Close();
660 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_FullBuffer) {
661 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
662 InitBuffer(test_stream);
663 // No expectations set on the strict mock because nothing should be called.
664 bool source_exhausted;
665 test_stream->packet_size_ = kTestPacketSize;
666 test_stream->BufferPacket(&source_exhausted);
667 EXPECT_EQ(kTestPacketSize, test_stream->buffer_->forward_bytes());
668 EXPECT_FALSE(source_exhausted);
669 test_stream->Close();
672 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_DeviceSelect) {
673 // Try channels from 1 -> 9. and see that we get the more specific surroundXX
674 // device opened for channels 4-8. For all other channels, the device should
675 // default to |AlsaPcmOutputStream::kDefaultDevice|. We should also not
676 // downmix any channel in this case because downmixing is only defined for
677 // channels 4-8, which we are guaranteeing to work.
679 // Note that the loop starts at "1", so the first parameter is ignored in
680 // these arrays.
681 const char* kExpectedDeviceName[] = { NULL,
682 AlsaPcmOutputStream::kDefaultDevice,
683 AlsaPcmOutputStream::kDefaultDevice,
684 AlsaPcmOutputStream::kDefaultDevice,
685 kSurround40, kSurround50, kSurround51,
686 kSurround70, kSurround71,
687 AlsaPcmOutputStream::kDefaultDevice };
688 bool kExpectedDownmix[] = { false, false, false, false, false, true,
689 false, false, false, false };
690 ChannelLayout kExpectedLayouts[] = { CHANNEL_LAYOUT_NONE,
691 CHANNEL_LAYOUT_MONO,
692 CHANNEL_LAYOUT_STEREO,
693 CHANNEL_LAYOUT_SURROUND,
694 CHANNEL_LAYOUT_4_0,
695 CHANNEL_LAYOUT_5_0,
696 CHANNEL_LAYOUT_5_1,
697 CHANNEL_LAYOUT_7_0,
698 CHANNEL_LAYOUT_7_1 };
701 for (int i = 1; i < 9; ++i) {
702 if (i == 3 || i == 4 || i == 5) // invalid number of channels
703 continue;
704 SCOPED_TRACE(base::StringPrintf("Attempting %d Channel", i));
706 // Hints will only be grabbed for channel numbers that have non-default
707 // devices associated with them.
708 if (kExpectedDeviceName[i] != AlsaPcmOutputStream::kDefaultDevice) {
709 // The DeviceNameHint and DeviceNameFreeHint need to be paired to avoid a
710 // memory leak.
711 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
712 .WillOnce(DoAll(SetArgumentPointee<2>(&kFakeHints[0]), Return(0)));
713 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
714 .Times(1);
717 EXPECT_CALL(mock_alsa_wrapper_,
718 PcmOpen(_, StrEq(kExpectedDeviceName[i]), _, _))
719 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
720 EXPECT_CALL(mock_alsa_wrapper_,
721 PcmSetParams(kFakeHandle, _, _, i, _, _, _))
722 .WillOnce(Return(0));
724 // The parameters are specified by ALSA documentation, and are in constants
725 // in the implementation files.
726 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
727 .WillRepeatedly(Invoke(OutputHint));
728 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
729 .WillRepeatedly(Invoke(EchoHint));
731 AlsaPcmOutputStream* test_stream = CreateStream(kExpectedLayouts[i]);
732 EXPECT_TRUE(test_stream->AutoSelectDevice(i));
733 EXPECT_EQ(kExpectedDownmix[i],
734 static_cast<bool>(test_stream->channel_mixer_));
736 Mock::VerifyAndClearExpectations(&mock_alsa_wrapper_);
737 Mock::VerifyAndClearExpectations(mock_manager_.get());
738 test_stream->Close();
742 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices) {
743 using std::string;
745 // If there are problems opening a multi-channel device, it the fallbacks
746 // operations should be as follows. Assume the multi-channel device name is
747 // surround50:
749 // 1) Try open "surround50"
750 // 2) Try open "plug:surround50".
751 // 3) Try open "default".
752 // 4) Try open "plug:default".
753 // 5) Give up trying to open.
755 const string first_try = kSurround50;
756 const string second_try = string(AlsaPcmOutputStream::kPlugPrefix) +
757 kSurround50;
758 const string third_try = AlsaPcmOutputStream::kDefaultDevice;
759 const string fourth_try = string(AlsaPcmOutputStream::kPlugPrefix) +
760 AlsaPcmOutputStream::kDefaultDevice;
762 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
763 .WillOnce(DoAll(SetArgumentPointee<2>(&kFakeHints[0]), Return(0)));
764 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameFreeHint(&kFakeHints[0]))
765 .Times(1);
766 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("IOID")))
767 .WillRepeatedly(Invoke(OutputHint));
768 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameGetHint(_, StrEq("NAME")))
769 .WillRepeatedly(Invoke(EchoHint));
770 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
771 .WillRepeatedly(Return(kDummyMessage));
773 InSequence s;
774 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(first_try.c_str()), _, _))
775 .WillOnce(Return(kTestFailedErrno));
776 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(second_try.c_str()), _, _))
777 .WillOnce(Return(kTestFailedErrno));
778 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(third_try.c_str()), _, _))
779 .WillOnce(Return(kTestFailedErrno));
780 EXPECT_CALL(mock_alsa_wrapper_, PcmOpen(_, StrEq(fourth_try.c_str()), _, _))
781 .WillOnce(Return(kTestFailedErrno));
783 AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
784 EXPECT_FALSE(test_stream->AutoSelectDevice(5));
785 test_stream->Close();
788 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_HintFail) {
789 // Should get |kDefaultDevice|, and force a 2-channel downmix on a failure to
790 // enumerate devices.
791 EXPECT_CALL(mock_alsa_wrapper_, DeviceNameHint(_, _, _))
792 .WillRepeatedly(Return(kTestFailedErrno));
793 EXPECT_CALL(mock_alsa_wrapper_,
794 PcmOpen(_, StrEq(AlsaPcmOutputStream::kDefaultDevice), _, _))
795 .WillOnce(DoAll(SetArgumentPointee<0>(kFakeHandle), Return(0)));
796 EXPECT_CALL(mock_alsa_wrapper_,
797 PcmSetParams(kFakeHandle, _, _, 2, _, _, _))
798 .WillOnce(Return(0));
799 EXPECT_CALL(mock_alsa_wrapper_, StrError(kTestFailedErrno))
800 .WillOnce(Return(kDummyMessage));
802 AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
803 EXPECT_TRUE(test_stream->AutoSelectDevice(5));
804 EXPECT_TRUE(test_stream->channel_mixer_);
805 test_stream->Close();
808 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_StopStream) {
809 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
810 InitBuffer(test_stream);
811 test_stream->stop_stream_ = true;
812 bool source_exhausted;
813 test_stream->BufferPacket(&source_exhausted);
814 EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
815 EXPECT_TRUE(source_exhausted);
816 test_stream->Close();
819 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite) {
820 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
821 test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
822 test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
823 InitBuffer(test_stream);
824 DVLOG(1) << test_stream->state();
825 EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(_))
826 .WillOnce(Return(10));
827 test_stream->ScheduleNextWrite(false);
828 DVLOG(1) << test_stream->state();
829 // TODO(sergeyu): Figure out how to check that the task has been added to the
830 // message loop.
832 // Cleanup the message queue. Currently ~MessageQueue() doesn't free pending
833 // tasks unless running on valgrind. The code below is needed to keep
834 // heapcheck happy.
836 test_stream->stop_stream_ = true;
837 DVLOG(1) << test_stream->state();
838 test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
839 DVLOG(1) << test_stream->state();
840 test_stream->Close();
843 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite_StopStream) {
844 AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
845 test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
846 test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
848 InitBuffer(test_stream);
850 test_stream->stop_stream_ = true;
851 test_stream->ScheduleNextWrite(true);
853 // TODO(ajwong): Find a way to test whether or not another task has been
854 // posted so we can verify that the Alsa code will indeed break the task
855 // posting loop.
857 test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
858 test_stream->Close();
861 } // namespace media