Index: content/renderer/media/audio_debug_recorder_unittest.cc |
diff --git a/content/renderer/media/audio_debug_recorder_unittest.cc b/content/renderer/media/audio_debug_recorder_unittest.cc |
new file mode 100644 |
index 0000000000000000000000000000000000000000..abe2ef4de1c3cb033030944449a8eecdc332bcb8 |
--- /dev/null |
+++ b/content/renderer/media/audio_debug_recorder_unittest.cc |
@@ -0,0 +1,247 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#include "content/renderer/media/audio_debug_recorder.h" |
+ |
+#include <map> |
+#include <utility> |
+ |
+#include "base/bind.h" |
+#include "base/files/file.h" |
+#include "base/files/scoped_temp_dir.h" |
+#include "base/memory/scoped_ptr.h" |
+#include "base/message_loop/message_loop.h" |
+#include "base/run_loop.h" |
+#include "content/common/media/audio_debug_recording.mojom.h" |
+#include "content/test/fake_service_registry.h" |
+#include "mojo/public/cpp/bindings/binding.h" |
+#include "mojo/public/cpp/system/handle.h" |
+#include "testing/gmock/include/gmock/gmock.h" |
+#include "testing/gtest/include/gtest/gtest.h" |
+#include "third_party/mojo/src/mojo/edk/embedder/embedder.h" |
+ |
+using ::testing::_; |
+using ::testing::Invoke; |
+using ::testing::InvokeWithoutArgs; |
+ |
+namespace content { |
+namespace { |
+ |
+mojo::ScopedHandle MojoHandleFromFile(base::File file) { |
+ CHECK(file.IsValid()); |
+ mojo::embedder::PlatformHandle platform_handle_wrapper( |
+ file.TakePlatformFile()); |
+ mojo::embedder::ScopedPlatformHandle scoped_platform_handle( |
+ platform_handle_wrapper); |
+ MojoHandle mojo_handle = MOJO_HANDLE_INVALID; |
+ MojoResult create_result = mojo::embedder::CreatePlatformHandleWrapper( |
+ std::move(scoped_platform_handle), &mojo_handle); |
+ CHECK_EQ(MOJO_RESULT_OK, create_result); |
+ return MakeScopedHandle(mojo::Handle(mojo_handle)); |
+} |
+ |
+class TestAudioDebugRecordingImpl : public AudioDebugRecording { |
+ public: |
+ TestAudioDebugRecordingImpl( |
+ mojo::InterfaceRequest<AudioDebugRecording> request) |
+ : binding_(this, std::move(request)) { |
+ } |
+ |
+ // |AudioDebugRecording| implementation. |
+ void RegisterObserver(int32_t id, |
+ AudioDebugRecordingObserverPtr observer) override { |
+ observer.set_connection_error_handler( |
+ base::Bind(&TestAudioDebugRecordingImpl::OnConnectionError, |
+ base::Unretained(this), id)); |
+ ASSERT_EQ(observers_.find(id), observers_.end()); |
+ observers_.insert(std::make_pair(id, make_scoped_ptr( |
+ new AudioDebugRecordingObserverPtr(std::move(observer))))); |
+ |
+ if (!quit_closure_.is_null()) |
+ quit_closure_.Run(); |
+ } |
+ |
+ void Enable(int32_t id, const base::FilePath& file_path) { |
+ auto it = observers_.find(id); |
+ ASSERT_NE(it, observers_.end()); |
+ base::File log_file(file_path, |
+ base::File::FLAG_CREATE | base::File::FLAG_WRITE); |
+ (*it->second)->Enable(MojoHandleFromFile(std::move(log_file))); |
+ } |
+ |
+ void Disable(int32_t id) { |
+ auto it = observers_.find(id); |
+ ASSERT_NE(it, observers_.end()); |
+ (*it->second)->Disable(); |
+ } |
+ |
+ size_t NumObservers() const { |
+ return observers_.size(); |
+ } |
+ |
+ void WaitForObservers(size_t num_observers) { |
+ base::RunLoop run_loop; |
+ quit_closure_ = run_loop.QuitClosure(); |
+ while (NumObservers() != num_observers) |
+ run_loop.Run(); |
+ quit_closure_ = base::Closure(); |
+ } |
+ |
+ private: |
+ void OnConnectionError(int32_t id) { |
+ auto it = observers_.find(id); |
+ ASSERT_NE(it, observers_.end()); |
+ observers_.erase(it); |
+ |
+ if (!quit_closure_.is_null()) |
+ quit_closure_.Run(); |
+ } |
+ |
+ base::Closure quit_closure_; |
+ std::map<int32_t, scoped_ptr<AudioDebugRecordingObserverPtr>> |
+ observers_; |
+ mojo::Binding<AudioDebugRecording> binding_; |
+}; |
+ |
+class MockDelegate : public AudioDebugRecorder::AecDumpDelegate { |
+ public: |
+ MockDelegate() {} |
+ |
+ MOCK_METHOD1(OnAecDumpFile, void(base::PlatformFile file_handle)); |
+ MOCK_METHOD0(OnDisableAecDump, void()); |
+ MOCK_METHOD0(OnIpcClosing, void()); |
+}; |
+ |
+} // namespace |
+ |
+class AudioDebugRecorderTest : public ::testing::Test { |
+ public: |
+ AudioDebugRecorderTest() { |
+ service_registry_.AddService( |
+ base::Bind(&AudioDebugRecorderTest::CreateService, |
+ base::Unretained(this))); |
+ } |
+ |
+ void CreateService(mojo::InterfaceRequest<AudioDebugRecording> request) { |
+ // There can be only one! |
+ ASSERT_EQ(nullptr, service_.get()); |
+ service_.reset(new TestAudioDebugRecordingImpl(std::move(request))); |
+ } |
+ |
+ base::MessageLoop message_loop_; |
+ FakeServiceRegistry service_registry_; |
+ scoped_ptr<TestAudioDebugRecordingImpl> service_; |
+}; |
+ |
+TEST_F(AudioDebugRecorderTest, GetGlobal) { |
+ EXPECT_EQ(nullptr, AudioDebugRecorder::Get()); |
+ { |
+ scoped_refptr<AudioDebugRecorder> recorder( |
+ new AudioDebugRecorder(&service_registry_)); |
+ EXPECT_EQ(recorder.get(), AudioDebugRecorder::Get()); |
+ } |
+ EXPECT_EQ(nullptr, AudioDebugRecorder::Get()); |
+} |
+ |
+TEST_F(AudioDebugRecorderTest, AddRemoveDelegate) { |
+ scoped_refptr<AudioDebugRecorder> recorder( |
+ new AudioDebugRecorder(&service_registry_)); |
+ ASSERT_NE(nullptr, service_.get()); |
+ EXPECT_EQ(0u, service_->NumObservers()); |
+ |
+ MockDelegate delegate1; |
+ recorder->AddDelegate(&delegate1); |
+ service_->WaitForObservers(1); |
+ |
+ MockDelegate delegate2; |
+ recorder->AddDelegate(&delegate2); |
+ service_->WaitForObservers(2); |
+ |
+ recorder->RemoveDelegate(&delegate1); |
+ service_->WaitForObservers(1); |
+ recorder->RemoveDelegate(&delegate2); |
+ service_->WaitForObservers(0); |
+} |
+ |
+TEST_F(AudioDebugRecorderTest, DeleteWithoutRemoving) { |
+ scoped_refptr<AudioDebugRecorder> recorder( |
+ new AudioDebugRecorder(&service_registry_)); |
+ ASSERT_NE(nullptr, service_.get()); |
+ EXPECT_EQ(0u, service_->NumObservers()); |
+ |
+ MockDelegate delegate1; |
+ recorder->AddDelegate(&delegate1); |
+ service_->WaitForObservers(1); |
+} |
+ |
+TEST_F(AudioDebugRecorderTest, EnableDisable) { |
+ scoped_refptr<AudioDebugRecorder> recorder( |
+ new AudioDebugRecorder(&service_registry_)); |
+ ASSERT_NE(nullptr, service_.get()); |
+ EXPECT_EQ(0u, service_->NumObservers()); |
+ |
+ MockDelegate delegate1; |
+ recorder->AddDelegate(&delegate1); |
+ service_->WaitForObservers(1); |
+ |
+ MockDelegate delegate2; |
+ recorder->AddDelegate(&delegate2); |
+ service_->WaitForObservers(2); |
+ |
+ base::ScopedTempDir temp_dir; |
+ ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); |
+ base::FilePath log1 = temp_dir.path().AppendASCII("log_file1"); |
+ base::FilePath log2 = temp_dir.path().AppendASCII("log_file2"); |
+ |
+ { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(delegate1, OnAecDumpFile(_)) |
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); |
+ service_->Enable(1, log1); |
+ run_loop.Run(); |
+ } |
+ |
+ { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(delegate2, OnAecDumpFile(_)) |
+ .WillOnce(InvokeWithoutArgs(&run_loop, &base::RunLoop::Quit)); |
+ service_->Enable(2, log2); |
+ run_loop.Run(); |
+ } |
+ |
+ { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(delegate1, OnDisableAecDump()) |
+ .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)); |
+ service_->Disable(1); |
+ run_loop.Run(); |
+ } |
+ |
+ { |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(delegate2, OnDisableAecDump()) |
+ .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)); |
+ service_->Disable(2); |
+ run_loop.Run(); |
+ } |
+} |
+ |
+TEST_F(AudioDebugRecorderTest, OnIpcClosing) { |
+ scoped_refptr<AudioDebugRecorder> recorder( |
+ new AudioDebugRecorder(&service_registry_)); |
+ ASSERT_NE(nullptr, service_.get()); |
+ EXPECT_EQ(0u, service_->NumObservers()); |
+ |
+ MockDelegate delegate1; |
+ recorder->AddDelegate(&delegate1); |
+ service_->WaitForObservers(1); |
+ |
+ base::RunLoop run_loop; |
+ EXPECT_CALL(delegate1, OnIpcClosing()) |
+ .WillOnce(Invoke(&run_loop, &base::RunLoop::Quit)); |
+ service_.reset(); |
+ run_loop.Run(); |
+} |
+ |
+} // namespace content |