Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright 2014 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/memory/shared_memory.h" | |
| 6 #include "base/message_loop/message_loop.h" | |
| 7 #include "base/process/process_handle.h" | |
| 8 #include "base/sync_socket.h" | |
| 9 #include "base/test/test_timeouts.h" | |
| 10 #include "media/audio/audio_device_thread.h" | |
| 11 #include "media/audio/audio_input_device.h" | |
| 12 #include "media/audio/audio_input_ipc.h" | |
| 13 #include "media/base/audio_capturer_source.h" | |
| 14 #include "testing/gmock/include/gmock/gmock.h" | |
| 15 #include "testing/gtest/include/gtest/gtest.h" | |
| 16 | |
| 17 using base::CancelableSyncSocket; | |
| 18 using base::SharedMemory; | |
| 19 using base::SyncSocket; | |
| 20 using testing::_; | |
| 21 using testing::StrictMock; | |
| 22 | |
| 23 namespace media { | |
| 24 | |
| 25 namespace { | |
| 26 | |
| 27 // The number of shared memory buffers used by AudioInputDevice. | |
| 28 static const int kNumOfSharedMemoriesInAID = 10; | |
| 29 | |
| 30 int CalculateMemorySize(const AudioParameters& params) { | |
| 31 return sizeof(AudioInputBufferParameters) + | |
| 32 AudioBus::CalculateMemorySize(params); | |
| 33 } | |
| 34 | |
| 35 // Creates a copy of a SyncSocket handle that we can give to AudioInputDevice. | |
| 36 // On Windows this means duplicating the pipe handle so that AudioInputDevice | |
| 37 // can call CloseHandle() (since ownership has been transferred), but on other | |
| 38 // platforms, we just copy the same socket handle since AudioInputDevice on | |
| 39 // those platforms won't actually own the socket (FileDescriptor.auto_close is | |
| 40 // false). | |
| 41 bool DuplicateSocketHandle(SyncSocket::Handle socket_handle, | |
| 42 SyncSocket::Handle* copy) { | |
| 43 #if defined(OS_WIN) | |
| 44 HANDLE process = GetCurrentProcess(); | |
| 45 ::DuplicateHandle(process, socket_handle, process, copy, | |
| 46 0, FALSE, DUPLICATE_SAME_ACCESS); | |
| 47 return *copy != NULL; | |
| 48 #else | |
| 49 *copy = socket_handle; | |
| 50 return *copy != -1; | |
| 51 #endif | |
| 52 } | |
| 53 | |
| 54 class MockCaptureCallback : public AudioCapturerSource::CaptureCallback { | |
| 55 public: | |
| 56 MockCaptureCallback() {} | |
| 57 virtual ~MockCaptureCallback() {} | |
| 58 | |
| 59 MOCK_METHOD4(Capture, void(const AudioBus* audio_source, | |
| 60 int audio_delay_milliseconds, | |
| 61 double volume, | |
| 62 bool key_pressed)); | |
| 63 MOCK_METHOD0(OnCaptureError, void()); | |
| 64 }; | |
| 65 | |
| 66 class MockAudioInputIPC : public AudioInputIPC { | |
| 67 public: | |
| 68 MockAudioInputIPC() {} | |
| 69 virtual ~MockAudioInputIPC() {} | |
| 70 | |
| 71 MOCK_METHOD5(CreateStream, void(AudioInputIPCDelegate* delegate, | |
| 72 int session_id, | |
| 73 const AudioParameters& params, | |
| 74 bool automatic_gain_control, | |
| 75 uint32 total_segments)); | |
| 76 MOCK_METHOD0(RecordStream, void()); | |
| 77 MOCK_METHOD1(SetVolume, void(double volume)); | |
| 78 MOCK_METHOD0(CloseStream, void()); | |
| 79 }; | |
| 80 | |
| 81 // Used to terminate a loop from a different thread than the loop belongs to. | |
| 82 // |loop| should be a SingleThreadTaskRunner. | |
| 83 ACTION_P(QuitLoop, task_runner) { | |
| 84 task_runner->PostTask(FROM_HERE, base::MessageLoop::QuitClosure()); | |
| 85 } | |
| 86 | |
| 87 } // namespace. | |
| 88 | |
| 89 class AudioInputDeviceTest : public testing::Test { | |
| 90 protected: | |
| 91 AudioInputDeviceTest() | |
| 92 : audio_parameters_(AudioParameters::AUDIO_PCM_LOW_LATENCY, | |
| 93 CHANNEL_LAYOUT_STEREO, | |
| 94 44100, | |
| 95 16, | |
| 96 441), | |
|
tommi (sloooow) - chröme
2014/09/02 12:03:34
Did you get a chance to run tests with very small
| |
| 97 io_loop_(new base::MessageLoopForIO), | |
| 98 mock_ipc_(new MockAudioInputIPC()), | |
| 99 audio_input_device_( | |
| 100 new AudioInputDevice(scoped_ptr<AudioInputIPC>(mock_ipc_), | |
| 101 io_loop_->message_loop_proxy())) { | |
| 102 audio_input_device_->Initialize(audio_parameters_, &callback_, 1); | |
| 103 io_loop_->RunUntilIdle(); | |
| 104 } | |
| 105 | |
| 106 virtual ~AudioInputDeviceTest() {} | |
| 107 | |
| 108 void StartAudioInputDevice() { | |
| 109 audio_input_device_->Start(); | |
| 110 EXPECT_CALL( | |
| 111 *mock_ipc_, | |
| 112 CreateStream( | |
| 113 audio_input_device_.get(), 1, _, false, kNumOfSharedMemoriesInAID)); | |
| 114 io_loop_->RunUntilIdle(); | |
| 115 } | |
| 116 | |
| 117 void CreateInputStream() { | |
| 118 const int kMemorySize = | |
| 119 CalculateMemorySize(audio_parameters_) * kNumOfSharedMemoriesInAID; | |
| 120 | |
| 121 ASSERT_TRUE(shared_memory_.CreateAndMapAnonymous(kMemorySize)); | |
| 122 memset(shared_memory_.memory(), 0xff, kMemorySize); | |
| 123 | |
| 124 ASSERT_TRUE( | |
| 125 CancelableSyncSocket::CreatePair(&browser_socket_, &renderer_socket_)); | |
| 126 | |
| 127 SyncSocket::Handle socket = SyncSocket::kInvalidHandle; | |
| 128 ASSERT_TRUE(DuplicateSocketHandle(renderer_socket_.handle(), | |
| 129 &socket)); | |
| 130 base::SharedMemoryHandle duplicated_memory_handle; | |
| 131 ASSERT_TRUE(shared_memory_.ShareToProcess(base::GetCurrentProcessHandle(), | |
| 132 &duplicated_memory_handle)); | |
| 133 | |
| 134 EXPECT_CALL(*mock_ipc_, RecordStream()); | |
| 135 audio_input_device_->OnStreamCreated(duplicated_memory_handle, | |
| 136 socket, | |
| 137 shared_memory_.requested_size(), | |
| 138 kNumOfSharedMemoriesInAID); | |
| 139 io_loop_->RunUntilIdle(); | |
| 140 } | |
| 141 | |
| 142 void WriteToSharedMemory() { | |
| 143 const size_t kSegmentSize = CalculateMemorySize(audio_parameters_); | |
| 144 uint8* ptr = static_cast<uint8*>(shared_memory_.memory()); | |
| 145 for (int i = 0; i < kNumOfSharedMemoriesInAID; ++i) { | |
| 146 AudioInputBuffer* buffer = reinterpret_cast<AudioInputBuffer*>(ptr); | |
| 147 buffer->params.volume = 0; | |
| 148 buffer->params.size = kSegmentSize; | |
| 149 buffer->params.key_pressed = false; | |
| 150 ptr += kSegmentSize; | |
| 151 } | |
| 152 } | |
| 153 | |
| 154 void ConsumeAndVerifySharedMemory() { | |
| 155 const size_t kSegmentSize = CalculateMemorySize(audio_parameters_); | |
| 156 uint8* ptr = static_cast<uint8*>(shared_memory_.memory()); | |
| 157 EXPECT_CALL(callback_, Capture(_, _, _, _)) | |
| 158 .WillRepeatedly(QuitLoop(io_loop_->task_runner())); | |
| 159 for (int i = 0; i < kNumOfSharedMemoriesInAID; ++i) { | |
| 160 AudioInputBuffer* buffer = reinterpret_cast<AudioInputBuffer*>(ptr); | |
| 161 EXPECT_EQ(kSegmentSize, buffer->params.size); | |
| 162 | |
| 163 // Send a socket from the browser to trigger processing the shared memory | |
| 164 // in AudioInputDevice. | |
| 165 int pending_bytes = 0; | |
| 166 browser_socket_.Send(&pending_bytes, sizeof(pending_bytes)); | |
| 167 WaitForCaptureCallback(); | |
| 168 | |
| 169 // Verify the |size| of the buffer has been reset to 0; | |
| 170 EXPECT_EQ(0u, buffer->params.size); | |
| 171 | |
| 172 // Iterate the next segment of shared memory. | |
| 173 ptr += kSegmentSize; | |
| 174 } | |
| 175 } | |
| 176 | |
| 177 void StopAudioInputDevice() { | |
| 178 audio_input_device_->Stop(); | |
| 179 EXPECT_CALL(*mock_ipc_, CloseStream()); | |
| 180 io_loop_->RunUntilIdle(); | |
| 181 } | |
| 182 | |
| 183 void WaitForCaptureCallback() { | |
| 184 io_loop_->PostDelayedTask(FROM_HERE, | |
| 185 base::MessageLoop::QuitClosure(), | |
| 186 TestTimeouts::action_timeout()); | |
| 187 io_loop_->Run(); | |
| 188 } | |
| 189 | |
| 190 protected: | |
| 191 AudioParameters audio_parameters_; | |
| 192 scoped_ptr<base::MessageLoopForIO> io_loop_; | |
| 193 MockAudioInputIPC* mock_ipc_; // owned by |audio_input_device_|. | |
| 194 scoped_refptr<AudioInputDevice> audio_input_device_; | |
| 195 StrictMock<MockCaptureCallback> callback_; | |
| 196 | |
| 197 private: | |
| 198 SharedMemory shared_memory_; | |
| 199 CancelableSyncSocket browser_socket_; | |
| 200 CancelableSyncSocket renderer_socket_; | |
| 201 | |
| 202 DISALLOW_COPY_AND_ASSIGN(AudioInputDeviceTest); | |
| 203 }; | |
| 204 | |
| 205 // Sets up shared memory and AudioInputDevice, and verify the shared memory | |
| 206 // is correctly written and consumed. | |
| 207 TEST_F(AudioInputDeviceTest, VerifySharedMemory) { | |
| 208 StartAudioInputDevice(); | |
| 209 CreateInputStream(); | |
| 210 WriteToSharedMemory(); | |
| 211 ConsumeAndVerifySharedMemory(); | |
| 212 StopAudioInputDevice(); | |
| 213 } | |
| 214 | |
| 215 } // namespace media. | |
| OLD | NEW |