| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright (c) 2016 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/bind.h" | 
|  | 6 #include "base/memory/shared_memory.h" | 
|  | 7 #include "base/run_loop.h" | 
|  | 8 #include "base/sync_socket.h" | 
|  | 9 #include "content/public/test/test_browser_thread.h" | 
|  | 10 #include "content/renderer/media/audio_message_filter.h" | 
|  | 11 #include "testing/gmock/include/gmock/gmock.h" | 
|  | 12 #include "testing/gtest/include/gtest/gtest.h" | 
|  | 13 /* | 
|  | 14 using ::testing::_; | 
|  | 15 | 
|  | 16 namespace content { | 
|  | 17 | 
|  | 18 namespace { | 
|  | 19 // const int kBufferSize1 = 30; | 
|  | 20 const int kBufferSize2 = 40; | 
|  | 21 const int kBufferSize3 = 50; | 
|  | 22 // const int kRenderFrameId = 5; | 
|  | 23 const int kStreamId1 = 9; | 
|  | 24 const int kStreamId2 = 20; | 
|  | 25 const int kStreamId3 = 3; | 
|  | 26 } | 
|  | 27 | 
|  | 28 class MockAudioMessageFilter : public AudioMessageFilter { | 
|  | 29  public: | 
|  | 30   MockAudioMessageFilter( | 
|  | 31       scoped_refptr<base::SingleThreadTaskRunner> io_task_runner) | 
|  | 32       : AudioMessageFilter(io_task_runner) {} | 
|  | 33   MOCK_METHOD4(OnStreamCreated, | 
|  | 34                void(int stream_id, | 
|  | 35                     base::SharedMemoryHandle handle, | 
|  | 36                     base::SyncSocket::TransitDescriptor socket_descriptor, | 
|  | 37                     uint32_t length)); | 
|  | 38   MOCK_METHOD2(OnStreamStateChanged, | 
|  | 39                void(int stream_id, media::AudioOutputIPCDelegateState state)); | 
|  | 40   MOCK_METHOD1(CloseStream, void(int stream_id)); | 
|  | 41 | 
|  | 42  protected: | 
|  | 43   ~MockAudioMessageFilter() {} | 
|  | 44 }; | 
|  | 45 | 
|  | 46 class TestAudioOutputImpl; | 
|  | 47 | 
|  | 48 class AudioOutputClientTest : public testing::Test { | 
|  | 49  public: | 
|  | 50   AudioOutputClientTest() { | 
|  | 51     message_loop_.reset(new base::MessageLoopForUI()); | 
|  | 52     io_thread_.reset( | 
|  | 53         new TestBrowserThread(BrowserThread::IO, message_loop_.get())); | 
|  | 54 | 
|  | 55     audio_output_client_ = | 
|  | 56         new AudioOutputClient(NULL, message_loop_->task_runner()); | 
|  | 57     audio_message_filter_ = | 
|  | 58         new MockAudioMessageFilter(message_loop_->task_runner()); | 
|  | 59   } | 
|  | 60 | 
|  | 61   void CreateStreamCallback(int stream_id, | 
|  | 62                             media::mojom::AudioOutputStreamPtr stream, | 
|  | 63                             mojo::ScopedSharedBufferHandle shared_buffer, | 
|  | 64                             mojo::ScopedHandle socket_descriptor) {} | 
|  | 65   static mojo::ScopedSharedBufferHandle GenerateBuffer(int buffer_size) { | 
|  | 66     base::SharedMemory shared_memory; | 
|  | 67     shared_memory.CreateAnonymous(buffer_size); | 
|  | 68     base::SharedMemoryHandle shared_memory_handle = shared_memory.handle(); | 
|  | 69 | 
|  | 70     MojoHandle mojo_foreign_memory_handle; | 
|  | 71 | 
|  | 72     MojoResult shared_buffer_result = mojo::edk::CreateSharedBufferWrapper( | 
|  | 73         shared_memory_handle, shared_memory.requested_size(), false, | 
|  | 74         &mojo_foreign_memory_handle); | 
|  | 75 | 
|  | 76     EXPECT_EQ(shared_buffer_result, MOJO_RESULT_OK); | 
|  | 77 | 
|  | 78     mojo::ScopedSharedBufferHandle shared_buffer_handle = | 
|  | 79         mojo::ScopedSharedBufferHandle( | 
|  | 80             mojo::SharedBufferHandle(mojo_foreign_memory_handle)); | 
|  | 81     return shared_buffer_handle; | 
|  | 82   } | 
|  | 83 | 
|  | 84   static mojo::ScopedHandle GenerateSocket() { | 
|  | 85     base::SyncSocket::TransitDescriptor socket_descriptor; | 
|  | 86 | 
|  | 87     MojoHandle socket_descriptor_handle; | 
|  | 88     MojoResult platform_handle_result; | 
|  | 89 | 
|  | 90 #if defined(OS_WIN) | 
|  | 91     platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( | 
|  | 92       mojo::edk::ScopedPlatformHandle( | 
|  | 93           mojo::edk::PlatformHandle(socket_descriptor), | 
|  | 94       &socket_descriptor_handle); | 
|  | 95 #else | 
|  | 96     platform_handle_result = mojo::edk::CreatePlatformHandleWrapper( | 
|  | 97         mojo::edk::ScopedPlatformHandle( | 
|  | 98             mojo::edk::PlatformHandle(socket_descriptor.fd)), | 
|  | 99         &socket_descriptor_handle); | 
|  | 100 #endif | 
|  | 101 | 
|  | 102   EXPECT_EQ(platform_handle_result, MOJO_RESULT_OK); | 
|  | 103 | 
|  | 104   mojo::ScopedHandle socket_handle = | 
|  | 105       mojo::ScopedHandle(mojo::Handle(socket_descriptor_handle)); | 
|  | 106   return socket_handle; | 
|  | 107   } | 
|  | 108 | 
|  | 109  protected: | 
|  | 110   scoped_refptr<AudioOutputClient> audio_output_client_; | 
|  | 111   std::unique_ptr<base::MessageLoop> message_loop_; | 
|  | 112   scoped_refptr<MockAudioMessageFilter> audio_message_filter_; | 
|  | 113   std::unique_ptr<TestAudioOutputImpl> audio_output_impl_; | 
|  | 114 | 
|  | 115  private: | 
|  | 116   std::unique_ptr<TestBrowserThread> io_thread_; | 
|  | 117   DISALLOW_COPY_AND_ASSIGN(AudioOutputClientTest); | 
|  | 118 }; | 
|  | 119 | 
|  | 120 class TestAudioOutputStreamImpl : public media::mojom::AudioOutputStream { | 
|  | 121  public: | 
|  | 122   TestAudioOutputStreamImpl(media::mojom::AudioOutputStreamRequest request) | 
|  | 123       : binding_(this, std::move(request)) {} | 
|  | 124   ~TestAudioOutputStreamImpl() override {} | 
|  | 125 | 
|  | 126   // AudioOutputStream implementation: | 
|  | 127   static base::RunLoop* run_loop_; | 
|  | 128   static int stream_count_; | 
|  | 129   void Close() override { | 
|  | 130     stream_count_--; | 
|  | 131     // The number of streams that will be closed is 2. | 
|  | 132     EXPECT_TRUE(stream_count_ > -1); | 
|  | 133     if (stream_count_ == 0) | 
|  | 134       run_loop_->Quit(); | 
|  | 135   } | 
|  | 136 | 
|  | 137  private: | 
|  | 138   mojo::Binding<media::mojom::AudioOutputStream> binding_; | 
|  | 139 }; | 
|  | 140 | 
|  | 141 class TestAudioOutputImpl : public media::mojom::AudioOutput { | 
|  | 142  public: | 
|  | 143   TestAudioOutputImpl(media::mojom::AudioOutputRequest request) | 
|  | 144       : binding_(this, std::move(request)) {} | 
|  | 145   ~TestAudioOutputImpl() override {} | 
|  | 146 | 
|  | 147   // AudioOutput implementation: | 
|  | 148   void CreateStream(int stream_id, | 
|  | 149                     const media::AudioParameters& params, | 
|  | 150                     const CreateStreamCallback& callback) override { | 
|  | 151     media::mojom::AudioOutputStreamPtr stream_ptr = | 
|  | 152         media::mojom::AudioOutputStreamPtr(); | 
|  | 153     std::unique_ptr<TestAudioOutputStreamImpl> stream( | 
|  | 154         new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr))); | 
|  | 155     mojo::ScopedSharedBufferHandle shared_buffer_handle = | 
|  | 156         mojo::ScopedSharedBufferHandle(mojo::SharedBufferHandle()); | 
|  | 157 | 
|  | 158     callback.Run(stream_id, std::move(stream_ptr), | 
|  | 159                  std::move(shared_buffer_handle), | 
|  | 160                  AudioOutputClientTest::GenerateSocket()); | 
|  | 161   } | 
|  | 162 | 
|  | 163  private: | 
|  | 164   mojo::Binding<media::mojom::AudioOutput> binding_; | 
|  | 165 }; | 
|  | 166 | 
|  | 167 base::RunLoop* TestAudioOutputStreamImpl::run_loop_; | 
|  | 168 int TestAudioOutputStreamImpl::stream_count_ = 2; | 
|  | 169 | 
|  | 170 TEST_F(AudioOutputClientTest, CreateStream) { | 
|  | 171   base::RunLoop run_loop; | 
|  | 172   media::mojom::AudioOutputPtr audio_output_impl_ptr; | 
|  | 173   audio_output_impl_.reset( | 
|  | 174       new TestAudioOutputImpl(mojo::GetProxy(&audio_output_impl_ptr))); | 
|  | 175   media::AudioParameters params( | 
|  | 176       media::AudioParameters::AUDIO_FAKE, media::CHANNEL_LAYOUT_STEREO, | 
|  | 177       media::AudioParameters::kAudioCDSampleRate, 16, | 
|  | 178       media::AudioParameters::kAudioCDSampleRate / 10); | 
|  | 179   int stream_count = 2; | 
|  | 180   audio_output_client_->service_ = std::move(audio_output_impl_ptr); | 
|  | 181 | 
|  | 182   audio_output_client_->CreateStream( | 
|  | 183       kStreamId1, params, | 
|  | 184       [&run_loop, &stream_count](int stream_id, | 
|  | 185                                  media::mojom::AudioOutputStreamPtr stream_ptr, | 
|  | 186                                  mojo::ScopedSharedBufferHandle shared_buffer, | 
|  | 187                                  mojo::ScopedHandle socket_descriptor) { | 
|  | 188         EXPECT_EQ(kStreamId1, stream_id); | 
|  | 189         EXPECT_TRUE(stream_ptr.is_bound()); | 
|  | 190         stream_count--; | 
|  | 191         // The number of streams that will be closed is 2. | 
|  | 192         EXPECT_TRUE(stream_count > -1); | 
|  | 193         if (stream_count == 1) | 
|  | 194           run_loop.Quit(); | 
|  | 195       }); | 
|  | 196 | 
|  | 197   audio_output_client_->CreateStream( | 
|  | 198       kStreamId2, params, | 
|  | 199       [&run_loop, &stream_count](int stream_id, | 
|  | 200                                  media::mojom::AudioOutputStreamPtr stream_ptr, | 
|  | 201                                  mojo::ScopedSharedBufferHandle shared_buffer, | 
|  | 202                                  mojo::ScopedHandle socket_descriptor) { | 
|  | 203         EXPECT_EQ(kStreamId2, stream_id); | 
|  | 204         EXPECT_TRUE(stream_ptr.is_bound()); | 
|  | 205         stream_count--; | 
|  | 206         // The number of streams that will be closed is 2. | 
|  | 207         EXPECT_TRUE(stream_count > -1); | 
|  | 208         if (stream_count == 0) | 
|  | 209           run_loop.Quit(); | 
|  | 210       }); | 
|  | 211   run_loop.Run(); | 
|  | 212 } | 
|  | 213 | 
|  | 214 TEST_F(AudioOutputClientTest, CreateStreamCallback) { | 
|  | 215   EXPECT_CALL(*audio_message_filter_, | 
|  | 216               OnStreamStateChanged( | 
|  | 217                   kStreamId2, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)) | 
|  | 218       .Times(0); | 
|  | 219   EXPECT_CALL(*audio_message_filter_, | 
|  | 220               OnStreamCreated(kStreamId2, _, _, kBufferSize2)) | 
|  | 221       .Times(1); | 
|  | 222 | 
|  | 223   media::mojom::AudioOutputStreamPtr stream_ptr2; | 
|  | 224   std::unique_ptr<TestAudioOutputStreamImpl> stream2( | 
|  | 225       new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr2))); | 
|  | 226 | 
|  | 227   audio_output_client_->CreateStreamCallback(kStreamId2, std::move(stream_ptr2), | 
|  | 228                                              GenerateBuffer(kBufferSize2), | 
|  | 229                                              GenerateSocket()); | 
|  | 230 | 
|  | 231   EXPECT_CALL(*audio_message_filter_, | 
|  | 232               OnStreamStateChanged( | 
|  | 233                   kStreamId3, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)) | 
|  | 234       .Times(0); | 
|  | 235   EXPECT_CALL(*audio_message_filter_, | 
|  | 236               OnStreamCreated(kStreamId3, _, _, kBufferSize3)) | 
|  | 237       .Times(1); | 
|  | 238   media::mojom::AudioOutputStreamPtr stream_ptr3; | 
|  | 239 | 
|  | 240   std::unique_ptr<TestAudioOutputStreamImpl> stream3( | 
|  | 241       new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr3))); | 
|  | 242 | 
|  | 243   audio_output_client_->CreateStreamCallback(kStreamId3, std::move(stream_ptr3), | 
|  | 244                                              GenerateBuffer(kBufferSize3), | 
|  | 245                                              GenerateSocket()); | 
|  | 246 | 
|  | 247   message_loop_->RunUntilIdle(); | 
|  | 248 } | 
|  | 249 | 
|  | 250 TEST_F(AudioOutputClientTest, CreateStreamCallbackNotFound) { | 
|  | 251   media::mojom::AudioOutputStreamPtr stream_ptr1; | 
|  | 252   EXPECT_CALL(*audio_message_filter_, | 
|  | 253               OnStreamStateChanged( | 
|  | 254                   kStreamId1, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)) | 
|  | 255       .Times(0); | 
|  | 256   EXPECT_CALL(*audio_message_filter_, | 
|  | 257               OnStreamStateChanged( | 
|  | 258                   kStreamId1, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)) | 
|  | 259       .Times(1); | 
|  | 260 | 
|  | 261   audio_output_client_->CreateStreamCallback(kStreamId1, std::move(stream_ptr1), | 
|  | 262                                              GenerateBuffer(kBufferSize1), | 
|  | 263                                              GenerateSocket()); | 
|  | 264 | 
|  | 265   EXPECT_CALL(*audio_message_filter_, | 
|  | 266               OnStreamStateChanged( | 
|  | 267                   kStreamId2, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)) | 
|  | 268       .Times(0); | 
|  | 269   EXPECT_CALL(*audio_message_filter_, | 
|  | 270               OnStreamCreated(kStreamId2, _, _, kBufferSize2)) | 
|  | 271       .Times(1); | 
|  | 272 | 
|  | 273   media::mojom::AudioOutputStreamPtr stream_ptr2; | 
|  | 274   std::unique_ptr<AudioOutputStreamImpl> stream2(new AudioOutputStreamImpl( | 
|  | 275       mojo::GetProxy(&stream_ptr2), kStreamId2, kRenderFrameId, NULL)); | 
|  | 276 | 
|  | 277   audio_output_client_->CreateStreamCallback(kStreamId2, std::move(stream_ptr2), | 
|  | 278                                              GenerateBuffer(kBufferSize2), | 
|  | 279                                              GenerateSocket()); | 
|  | 280 | 
|  | 281   EXPECT_CALL(*audio_message_filter_, | 
|  | 282               OnStreamStateChanged( | 
|  | 283                   kStreamId3, media::AUDIO_OUTPUT_IPC_DELEGATE_STATE_ERROR)) | 
|  | 284       .Times(0); | 
|  | 285   EXPECT_CALL(*audio_message_filter_, | 
|  | 286               OnStreamCreated(kStreamId3, _, _, kBufferSize3)) | 
|  | 287       .Times(1); | 
|  | 288   media::mojom::AudioOutputStreamPtr stream_ptr3; | 
|  | 289 | 
|  | 290   std::unique_ptr<AudioOutputStreamImpl> stream3(new AudioOutputStreamImpl( | 
|  | 291       mojo::GetProxy(&stream_ptr3), kStreamId3, kRenderFrameId, NULL)); | 
|  | 292 | 
|  | 293   audio_output_client_->CreateStreamCallback(kStreamId3, std::move(stream_ptr3), | 
|  | 294                                              GenerateBuffer(kBufferSize3), | 
|  | 295                                              GenerateSocket()); | 
|  | 296 | 
|  | 297   message_loop_->RunUntilIdle(); | 
|  | 298 } | 
|  | 299 | 
|  | 300 TEST_F(AudioOutputClientTest, CloseAuthorizedNotCreatedStream) { | 
|  | 301   base::RunLoop run_loop; | 
|  | 302   media::mojom::AudioOutputPtr audio_output_impl_ptr; | 
|  | 303   audio_output_impl_.reset( | 
|  | 304       new TestAudioOutputImpl(mojo::GetProxy(&audio_output_impl_ptr))); | 
|  | 305   audio_output_client_->service_ = std::move(audio_output_impl_ptr); | 
|  | 306 | 
|  | 307   EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId1)).Times(1); | 
|  | 308 | 
|  | 309   audio_output_client_->CloseStream(kStreamId1); | 
|  | 310 | 
|  | 311   EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId2)).Times(1); | 
|  | 312   audio_output_client_->CloseStream(kStreamId2); | 
|  | 313 } | 
|  | 314 | 
|  | 315 TEST_F(AudioOutputClientTest, CloseCreatedStream) { | 
|  | 316   TestAudioOutputStreamImpl::run_loop_ = new base::RunLoop(); | 
|  | 317   media::mojom::AudioOutputPtr audio_output_impl_ptr; | 
|  | 318   audio_output_impl_.reset( | 
|  | 319       new TestAudioOutputImpl(mojo::GetProxy(&audio_output_impl_ptr))); | 
|  | 320   audio_output_client_->service_ = std::move(audio_output_impl_ptr); | 
|  | 321 | 
|  | 322   media::mojom::AudioOutputStreamPtr stream_ptr1; | 
|  | 323   std::unique_ptr<TestAudioOutputStreamImpl> stream1( | 
|  | 324       new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr1))); | 
|  | 325   audio_output_client_->streams_.insert( | 
|  | 326       std::make_pair(kStreamId1, std::move(stream_ptr1))); | 
|  | 327 | 
|  | 328   // Closing an authorized but ńot created stream should call | 
|  | 329   // AudioMessageFilter::CloseStream. | 
|  | 330   EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId3)).Times(1); | 
|  | 331 | 
|  | 332   audio_output_client_->CloseStream(kStreamId3); | 
|  | 333 | 
|  | 334   audio_output_client_->CloseStream(kStreamId1); | 
|  | 335 | 
|  | 336   media::mojom::AudioOutputStreamPtr stream_ptr2; | 
|  | 337   std::unique_ptr<TestAudioOutputStreamImpl> stream2( | 
|  | 338       new TestAudioOutputStreamImpl(mojo::GetProxy(&stream_ptr2))); | 
|  | 339   audio_output_client_->streams_.insert( | 
|  | 340       std::make_pair(kStreamId2, std::move(stream_ptr2))); | 
|  | 341   audio_output_client_->CloseStream(kStreamId2); | 
|  | 342   TestAudioOutputStreamImpl::run_loop_->Run(); | 
|  | 343 | 
|  | 344   // |kStreamId1| is cllosed now. Closing it will call | 
|  | 345   // AudioMessageFilter::CloseStream. The same for |kStreamId2| | 
|  | 346   EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId1)).Times(1); | 
|  | 347   audio_output_client_->CloseStream(kStreamId1); | 
|  | 348 | 
|  | 349   EXPECT_CALL(*audio_message_filter_, CloseStream(kStreamId2)).Times(1); | 
|  | 350   audio_output_client_->CloseStream(kStreamId2); | 
|  | 351 } | 
|  | 352 | 
|  | 353 }  // namespace content | 
|  | 354 */ | 
| OLD | NEW | 
|---|