OLD | NEW |
(Empty) | |
| 1 // Copyright 2017 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 "media/mojo/services/mojo_audio_output.h" |
| 6 |
| 7 #include <utility> |
| 8 |
| 9 #include "base/memory/shared_memory.h" |
| 10 #include "base/message_loop/message_loop.h" |
| 11 #include "base/run_loop.h" |
| 12 #include "base/sync_socket.h" |
| 13 #include "media/audio/audio_output_controller.h" |
| 14 #include "media/mojo/interfaces/audio_output.mojom.h" |
| 15 #include "mojo/public/cpp/system/platform_handle.h" |
| 16 #include "testing/gmock/include/gmock/gmock.h" |
| 17 #include "testing/gtest/include/gtest/gtest.h" |
| 18 |
| 19 namespace media { |
| 20 |
| 21 namespace { |
| 22 |
| 23 const double kNewVolume = 0.618; |
| 24 // Not actually used, but sent from the AudioOutputDelegate. |
| 25 const int kStreamId = 0; |
| 26 const int kShmemSize = 100; |
| 27 |
| 28 using testing::_; |
| 29 using testing::Mock; |
| 30 using testing::NotNull; |
| 31 using testing::Return; |
| 32 using testing::SaveArg; |
| 33 using testing::StrictMock; |
| 34 using testing::Test; |
| 35 using AudioOutput = mojom::AudioOutput; |
| 36 using AudioOutputPtr = mojo::InterfacePtr<AudioOutput>; |
| 37 |
| 38 class MockDelegate : public AudioOutputDelegate { |
| 39 public: |
| 40 MOCK_CONST_METHOD0(GetController, scoped_refptr<AudioOutputController>()); |
| 41 MOCK_CONST_METHOD0(GetStreamId, int()); |
| 42 MOCK_METHOD0(OnPlayStream, void()); |
| 43 MOCK_METHOD0(OnPauseStream, void()); |
| 44 MOCK_METHOD1(OnSetVolume, void(double)); |
| 45 }; |
| 46 |
| 47 class MockDelegateFactory { |
| 48 public: |
| 49 void PrepareDelegateForCreation( |
| 50 std::unique_ptr<AudioOutputDelegate> delegate) { |
| 51 ASSERT_EQ(nullptr, delegate_); |
| 52 delegate_.swap(delegate); |
| 53 } |
| 54 |
| 55 std::unique_ptr<AudioOutputDelegate> CreateDelegate( |
| 56 AudioOutputDelegate::EventHandler* handler) { |
| 57 MockCreateDelegate(handler); |
| 58 EXPECT_NE(nullptr, delegate_); |
| 59 return std::move(delegate_); |
| 60 } |
| 61 |
| 62 MOCK_METHOD1(MockCreateDelegate, void(AudioOutputDelegate::EventHandler*)); |
| 63 |
| 64 private: |
| 65 std::unique_ptr<AudioOutputDelegate> delegate_; |
| 66 }; |
| 67 |
| 68 class MockDeleter { |
| 69 public: |
| 70 MOCK_METHOD0(Finished, void()); |
| 71 }; |
| 72 |
| 73 class MockClient { |
| 74 public: |
| 75 MockClient() {} |
| 76 |
| 77 void Initialized(mojo::ScopedSharedBufferHandle shared_buffer, |
| 78 mojo::ScopedHandle socket_handle) { |
| 79 ASSERT_TRUE(shared_buffer.is_valid()); |
| 80 ASSERT_TRUE(socket_handle.is_valid()); |
| 81 |
| 82 base::PlatformFile fd; |
| 83 mojo::UnwrapPlatformFile(std::move(socket_handle), &fd); |
| 84 socket_ = base::MakeUnique<base::CancelableSyncSocket>(fd); |
| 85 EXPECT_NE(socket_->handle(), base::CancelableSyncSocket::kInvalidHandle); |
| 86 |
| 87 size_t memory_length; |
| 88 base::SharedMemoryHandle shmem_handle; |
| 89 bool read_only; |
| 90 EXPECT_EQ( |
| 91 mojo::UnwrapSharedMemoryHandle(std::move(shared_buffer), &shmem_handle, |
| 92 &memory_length, &read_only), |
| 93 MOJO_RESULT_OK); |
| 94 EXPECT_FALSE(read_only); |
| 95 buffer_ = base::MakeUnique<base::SharedMemory>(shmem_handle, read_only); |
| 96 |
| 97 GotNotification(); |
| 98 } |
| 99 |
| 100 MOCK_METHOD0(GotNotification, void()); |
| 101 |
| 102 private: |
| 103 std::unique_ptr<base::SharedMemory> buffer_; |
| 104 std::unique_ptr<base::CancelableSyncSocket> socket_; |
| 105 }; |
| 106 |
| 107 } // namespace |
| 108 |
| 109 class MojoAudioOutputTest : public Test { |
| 110 public: |
| 111 MojoAudioOutputTest() {} |
| 112 |
| 113 AudioOutputPtr CreateAudioOutput() { |
| 114 AudioOutputPtr p; |
| 115 ExpectDelegateCreation(); |
| 116 impl_ = base::MakeUnique<MojoAudioOutput>( |
| 117 mojo::MakeRequest(&p), |
| 118 base::BindOnce(&MockDelegateFactory::CreateDelegate, |
| 119 base::Unretained(&mock_delegate_factory_)), |
| 120 base::Bind(&MockClient::Initialized, base::Unretained(&client_)), |
| 121 base::BindOnce(&MockDeleter::Finished, base::Unretained(&deleter_))); |
| 122 EXPECT_NE(nullptr, p); |
| 123 return p; |
| 124 } |
| 125 |
| 126 protected: |
| 127 void ExpectDelegateCreation() { |
| 128 delegate_ = new StrictMock<MockDelegate>(); |
| 129 mock_delegate_factory_.PrepareDelegateForCreation( |
| 130 base::WrapUnique(delegate_)); |
| 131 EXPECT_TRUE( |
| 132 base::CancelableSyncSocket::CreatePair(&local_, &foreign_socket_)); |
| 133 EXPECT_TRUE(mem_.CreateAnonymous(kShmemSize)); |
| 134 EXPECT_CALL(mock_delegate_factory_, MockCreateDelegate(NotNull())) |
| 135 .WillOnce(SaveArg<0>(&delegate_event_handler_)); |
| 136 } |
| 137 |
| 138 base::MessageLoop loop_; |
| 139 base::CancelableSyncSocket local_, foreign_socket_; |
| 140 base::SharedMemory mem_; |
| 141 StrictMock<MockDelegate>* delegate_ = nullptr; |
| 142 AudioOutputDelegate::EventHandler* delegate_event_handler_ = nullptr; |
| 143 StrictMock<MockDelegateFactory> mock_delegate_factory_; |
| 144 StrictMock<MockDeleter> deleter_; |
| 145 MockClient client_; |
| 146 std::unique_ptr<MojoAudioOutput> impl_; |
| 147 }; |
| 148 |
| 149 TEST_F(MojoAudioOutputTest, Play_Plays) { |
| 150 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 151 EXPECT_CALL(*delegate_, OnPlayStream()); |
| 152 |
| 153 audio_output_ptr->Play(); |
| 154 base::RunLoop().RunUntilIdle(); |
| 155 } |
| 156 |
| 157 TEST_F(MojoAudioOutputTest, Pause_Pauses) { |
| 158 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 159 EXPECT_CALL(*delegate_, OnPauseStream()); |
| 160 |
| 161 audio_output_ptr->Pause(); |
| 162 base::RunLoop().RunUntilIdle(); |
| 163 } |
| 164 |
| 165 TEST_F(MojoAudioOutputTest, SetVolume_SetsVolume) { |
| 166 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 167 EXPECT_CALL(*delegate_, OnSetVolume(kNewVolume)); |
| 168 |
| 169 audio_output_ptr->SetVolume(kNewVolume); |
| 170 base::RunLoop().RunUntilIdle(); |
| 171 } |
| 172 |
| 173 TEST_F(MojoAudioOutputTest, DestructWithCallPending_Safe) { |
| 174 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 175 base::RunLoop().RunUntilIdle(); |
| 176 |
| 177 ASSERT_NE(nullptr, delegate_event_handler_); |
| 178 delegate_event_handler_->OnStreamCreated(kStreamId, &mem_, &foreign_socket_); |
| 179 audio_output_ptr->Play(); |
| 180 impl_.reset(); |
| 181 base::RunLoop().RunUntilIdle(); |
| 182 } |
| 183 |
| 184 TEST_F(MojoAudioOutputTest, Created_NotifiesClient) { |
| 185 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 186 base::RunLoop().RunUntilIdle(); |
| 187 |
| 188 EXPECT_CALL(client_, GotNotification()); |
| 189 |
| 190 ASSERT_NE(nullptr, delegate_event_handler_); |
| 191 delegate_event_handler_->OnStreamCreated(kStreamId, &mem_, &foreign_socket_); |
| 192 |
| 193 base::RunLoop().RunUntilIdle(); |
| 194 } |
| 195 |
| 196 TEST_F(MojoAudioOutputTest, SetVolumeTooLarge_Error) { |
| 197 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 198 EXPECT_CALL(deleter_, Finished()); |
| 199 |
| 200 audio_output_ptr->SetVolume(15); |
| 201 base::RunLoop().RunUntilIdle(); |
| 202 Mock::VerifyAndClear(&deleter_); |
| 203 } |
| 204 |
| 205 TEST_F(MojoAudioOutputTest, SetVolumeNegative_Error) { |
| 206 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 207 EXPECT_CALL(deleter_, Finished()); |
| 208 |
| 209 audio_output_ptr->SetVolume(-0.5); |
| 210 base::RunLoop().RunUntilIdle(); |
| 211 Mock::VerifyAndClear(&deleter_); |
| 212 } |
| 213 |
| 214 TEST_F(MojoAudioOutputTest, DelegateErrorBeforeCreated_PropagatesError) { |
| 215 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 216 EXPECT_CALL(deleter_, Finished()); |
| 217 |
| 218 ASSERT_NE(nullptr, delegate_event_handler_); |
| 219 delegate_event_handler_->OnStreamError(kStreamId); |
| 220 |
| 221 base::RunLoop().RunUntilIdle(); |
| 222 Mock::VerifyAndClear(&deleter_); |
| 223 } |
| 224 |
| 225 TEST_F(MojoAudioOutputTest, DelegateErrorAfterCreated_PropagatesError) { |
| 226 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 227 EXPECT_CALL(deleter_, Finished()); |
| 228 base::RunLoop().RunUntilIdle(); |
| 229 |
| 230 ASSERT_NE(nullptr, delegate_event_handler_); |
| 231 delegate_event_handler_->OnStreamCreated(kStreamId, &mem_, &foreign_socket_); |
| 232 delegate_event_handler_->OnStreamError(kStreamId); |
| 233 |
| 234 base::RunLoop().RunUntilIdle(); |
| 235 Mock::VerifyAndClear(&deleter_); |
| 236 } |
| 237 |
| 238 TEST_F(MojoAudioOutputTest, RemoteEndGone_Error) { |
| 239 AudioOutputPtr audio_output_ptr = CreateAudioOutput(); |
| 240 EXPECT_CALL(deleter_, Finished()); |
| 241 audio_output_ptr.reset(); |
| 242 base::RunLoop().RunUntilIdle(); |
| 243 Mock::VerifyAndClear(&deleter_); |
| 244 } |
| 245 |
| 246 } // namespace media |
OLD | NEW |