Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / media / audio / alsa / alsa_output_unittest.cc
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.
4
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"
15
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;
31
32 namespace media {
33
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));
41
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));
66
67   MOCK_METHOD1(StrError, const char*(int errnum));
68 };
69
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));
83
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;
91   }
92
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();
97   }
98
99  private:
100   FakeAudioLogFactory fake_audio_log_factory_;
101 };
102
103 class AlsaPcmOutputStreamTest : public testing::Test {
104  protected:
105   AlsaPcmOutputStreamTest() {
106     mock_manager_.reset(new StrictMock<MockAudioManagerAlsa>());
107   }
108
109   virtual ~AlsaPcmOutputStreamTest() {
110   }
111
112   AlsaPcmOutputStream* CreateStream(ChannelLayout layout) {
113     return CreateStream(layout, kTestFramesPerPacket);
114   }
115
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());
124   }
125
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));
129   }
130
131   // Helper function to malloc the string returned by DeviceNameHint for IOID.
132   static char* OutputHint(Unused, Unused) {
133     return strdup("Output");
134   }
135
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());
144   }
145
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;
157
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[];
166
167   StrictMock<MockAlsaWrapper> mock_alsa_wrapper_;
168   scoped_ptr<StrictMock<MockAudioManagerAlsa> > mock_manager_;
169   base::MessageLoop message_loop_;
170   scoped_refptr<media::DataBuffer> packet_;
171
172  private:
173   DISALLOW_COPY_AND_ASSIGN(AlsaPcmOutputStreamTest);
174 };
175
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);
195
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 };
205
206 // Custom action to clear a memory buffer.
207 ACTION(ClearBuffer) {
208   arg0->Zero();
209 }
210
211 TEST_F(AlsaPcmOutputStreamTest, ConstructedState) {
212   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
213   EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
214   test_stream->Close();
215
216   // Should support mono.
217   test_stream = CreateStream(CHANNEL_LAYOUT_MONO);
218   EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
219   test_stream->Close();
220
221   // Should support multi-channel.
222   test_stream = CreateStream(CHANNEL_LAYOUT_SURROUND);
223   EXPECT_EQ(AlsaPcmOutputStream::kCreated, test_stream->state());
224   test_stream->Close();
225
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();
236
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();
247 }
248
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;
254
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)));
269
270   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout,
271                                                   kPacketFramesInMinLatency);
272   ASSERT_TRUE(test_stream->Open());
273
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();
279
280   Mock::VerifyAndClear(&mock_alsa_wrapper_);
281   Mock::VerifyAndClear(mock_manager_.get());
282
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();
287
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)));
297
298   test_stream = CreateStream(kTestChannelLayout,
299                              kOverMinLatencyPacketSize);
300   ASSERT_TRUE(test_stream->Open());
301
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();
308
309   Mock::VerifyAndClear(&mock_alsa_wrapper_);
310   Mock::VerifyAndClear(mock_manager_.get());
311 }
312
313 TEST_F(AlsaPcmOutputStreamTest, OpenClose) {
314   int64 expected_micros = AlsaPcmOutputStream::FramesToTimeDelta(
315       2 * kTestFramesPerPacket, kTestSampleRate).InMicroseconds();
316
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,
331                            1,
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)));
338
339   // Open the stream.
340   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
341   ASSERT_TRUE(test_stream->Open());
342
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_);
348
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();
355 }
356
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));
362
363   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
364   ASSERT_FALSE(test_stream->Open());
365   ASSERT_EQ(AlsaPcmOutputStream::kInError, test_stream->state());
366
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());
371
372   // Close the stream since we opened it to make destruction happy.
373   test_stream->Close();
374 }
375
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));
388
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());
394
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());
399
400   // Close the stream since we opened it to make destruction happy.
401   test_stream->Close();
402 }
403
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)));
417
418   // Open the stream.
419   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
420   ASSERT_TRUE(test_stream->Open());
421
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));
427
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));
438
439   // Expect scheduling.
440   EXPECT_CALL(mock_alsa_wrapper_, PcmAvailUpdate(kFakeHandle))
441       .Times(AtLeast(2))
442       .WillRepeatedly(Return(kTestFramesPerPacket));
443
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();
450
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();
456 }
457
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);
463
464   // Nothing should happen.  Don't set any expectations and Our strict mocks
465   // should verify most of this.
466
467   // Test empty buffer.
468   test_stream->buffer_->Clear();
469   test_stream->WritePacket();
470   test_stream->Close();
471 }
472
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);
488
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));
495
496   test_stream->WritePacket();
497
498   ASSERT_EQ(test_stream->buffer_->forward_bytes(),
499             packet_->data_size() - written * kTestBytesPerFrame);
500
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,
507                         _))
508       .WillOnce(Return(packet_->data_size() / kTestBytesPerFrame - written));
509   test_stream->WritePacket();
510   EXPECT_EQ(0, test_stream->buffer_->forward_bytes());
511
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();
518 }
519
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);
535
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));
544
545   test_stream->WritePacket();
546
547   ASSERT_EQ(test_stream->buffer_->forward_bytes(), packet_->data_size());
548
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_);
561
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();
568 }
569
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);
575
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();
581 }
582
583 TEST_F(AlsaPcmOutputStreamTest, BufferPacket) {
584   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
585   InitBuffer(test_stream);
586   test_stream->buffer_->Clear();
587
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.
595
596   // Return a partially filled packet.
597   EXPECT_CALL(mock_callback, OnMoreData(_, _))
598       .WillOnce(DoAll(ClearBuffer(), Return(kTestFramesPerPacket / 2)));
599
600   bool source_exhausted;
601   test_stream->set_source_callback(&mock_callback);
602   test_stream->packet_size_ = kTestPacketSize;
603   test_stream->BufferPacket(&source_exhausted);
604
605   EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
606   EXPECT_FALSE(source_exhausted);
607   test_stream->Close();
608 }
609
610 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Negative) {
611   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
612   InitBuffer(test_stream);
613   test_stream->buffer_->Clear();
614
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)));
625
626   bool source_exhausted;
627   test_stream->set_source_callback(&mock_callback);
628   test_stream->packet_size_ = kTestPacketSize;
629   test_stream->BufferPacket(&source_exhausted);
630
631   EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
632   EXPECT_FALSE(source_exhausted);
633   test_stream->Close();
634 }
635
636 TEST_F(AlsaPcmOutputStreamTest, BufferPacket_Underrun) {
637   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
638   InitBuffer(test_stream);
639   test_stream->buffer_->Clear();
640
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)));
649
650   bool source_exhausted;
651   test_stream->set_source_callback(&mock_callback);
652   test_stream->packet_size_ = kTestPacketSize;
653   test_stream->BufferPacket(&source_exhausted);
654
655   EXPECT_EQ(kTestPacketSize / 2, test_stream->buffer_->forward_bytes());
656   EXPECT_FALSE(source_exhausted);
657   test_stream->Close();
658 }
659
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();
670 }
671
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.
678   //
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 };
699
700
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));
705
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);
715     }
716
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));
723
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));
730
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_));
735
736     Mock::VerifyAndClearExpectations(&mock_alsa_wrapper_);
737     Mock::VerifyAndClearExpectations(mock_manager_.get());
738     test_stream->Close();
739   }
740 }
741
742 TEST_F(AlsaPcmOutputStreamTest, AutoSelectDevice_FallbackDevices) {
743   using std::string;
744
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:
748   //
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.
754   //
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;
761
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));
772
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));
782
783   AlsaPcmOutputStream* test_stream = CreateStream(CHANNEL_LAYOUT_5_0);
784   EXPECT_FALSE(test_stream->AutoSelectDevice(5));
785   test_stream->Close();
786 }
787
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));
801
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();
806 }
807
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();
817 }
818
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.
831
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.
835
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();
841 }
842
843 TEST_F(AlsaPcmOutputStreamTest, ScheduleNextWrite_StopStream) {
844   AlsaPcmOutputStream* test_stream = CreateStream(kTestChannelLayout);
845   test_stream->TransitionTo(AlsaPcmOutputStream::kIsOpened);
846   test_stream->TransitionTo(AlsaPcmOutputStream::kIsPlaying);
847
848   InitBuffer(test_stream);
849
850   test_stream->stop_stream_ = true;
851   test_stream->ScheduleNextWrite(true);
852
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.
856
857   test_stream->TransitionTo(AlsaPcmOutputStream::kIsClosed);
858   test_stream->Close();
859 }
860
861 }  // namespace media