blob: f0102abfd8d3595422a5241152224177f6ca3a7d [file] [log] [blame]
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "media/audio/aecdump_recording_manager.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/functional/bind.h"
#include "base/test/task_environment.h"
#include "base/test/test_file_util.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
using testing::_;
using testing::InSequence;
using testing::NiceMock;
using testing::Sequence;
namespace media {
namespace {
class MockAecdumpRecordingSource : public AecdumpRecordingSource {
public:
MOCK_METHOD1(StartAecdump, void(base::File));
MOCK_METHOD0(StopAecdump, void());
};
class AecdumpRecordingManagerTest : public ::testing::Test {
public:
AecdumpRecordingManagerTest()
: manager_(std::make_unique<AecdumpRecordingManager>(
task_environment_.GetMainThreadTaskRunner())),
create_file_callback_(base::BindRepeating(
&AecdumpRecordingManagerTest::AsyncCreateFileCallback,
base::Unretained(this))) {}
void SetUp() override {
temp_dir_path_ = base::CreateUniqueTempDirectoryScopedToTest();
}
void TearDown() override { task_environment_.RunUntilIdle(); }
protected:
// Simulates async file creation by posting the reply to the main thread.
void AsyncCreateFileCallback(
uint32_t /*id*/,
base::OnceCallback<void(base::File)> reply_callback) {
base::FilePath temp_file_path;
base::File file =
base::CreateAndOpenTemporaryFileInDir(temp_dir_path_, &temp_file_path);
ASSERT_TRUE(file.IsValid());
task_environment_.GetMainThreadTaskRunner()->PostTask(
FROM_HERE, base::BindOnce(std::move(reply_callback), std::move(file)));
}
base::FilePath temp_dir_path_;
base::test::TaskEnvironment task_environment_;
std::unique_ptr<AecdumpRecordingManager> manager_;
AecdumpRecordingManager::CreateFileCallback create_file_callback_;
};
TEST_F(AecdumpRecordingManagerTest, EnableDisableDoesNotCrash) {
manager_->EnableDebugRecording(create_file_callback_);
manager_->DisableDebugRecording();
}
TEST_F(AecdumpRecordingManagerTest,
EnableDisableWithOneSourceStartsStopsSource) {
MockAecdumpRecordingSource mock_source;
InSequence s;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(1);
EXPECT_CALL(mock_source, StopAecdump()).Times(1);
manager_->RegisterAecdumpSource(&mock_source);
manager_->EnableDebugRecording(create_file_callback_);
base::RunLoop().RunUntilIdle();
manager_->DisableDebugRecording();
manager_->DeregisterAecdumpSource(&mock_source);
}
TEST_F(AecdumpRecordingManagerTest,
EnableDisableWithTwoSourcesStartsStopsSources) {
MockAecdumpRecordingSource mock_source_a;
MockAecdumpRecordingSource mock_source_b;
Sequence s1;
Sequence s2;
EXPECT_CALL(mock_source_a, StartAecdump(_)).Times(1).InSequence(s1);
EXPECT_CALL(mock_source_a, StopAecdump()).Times(1).InSequence(s1);
EXPECT_CALL(mock_source_b, StartAecdump(_)).Times(1).InSequence(s2);
EXPECT_CALL(mock_source_b, StopAecdump()).Times(1).InSequence(s2);
manager_->RegisterAecdumpSource(&mock_source_a);
manager_->RegisterAecdumpSource(&mock_source_b);
manager_->EnableDebugRecording(create_file_callback_);
base::RunLoop().RunUntilIdle();
manager_->DisableDebugRecording();
manager_->DeregisterAecdumpSource(&mock_source_a);
manager_->DeregisterAecdumpSource(&mock_source_b);
}
TEST_F(AecdumpRecordingManagerTest,
RegisterDeregisterSourceBeforeEnableDisableDoesNotStartStopSource) {
MockAecdumpRecordingSource mock_source;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(0);
EXPECT_CALL(mock_source, StopAecdump()).Times(0);
manager_->RegisterAecdumpSource(&mock_source);
manager_->DeregisterAecdumpSource(&mock_source);
// Enabling debug recordings should not trigger any calls to the recording
// source.
manager_->EnableDebugRecording(create_file_callback_);
base::RunLoop().RunUntilIdle();
manager_->DisableDebugRecording();
}
TEST_F(AecdumpRecordingManagerTest,
RegisterDeregisterSourceAfterEnableDisableDoesNotStartStopSource) {
MockAecdumpRecordingSource mock_source;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(0);
EXPECT_CALL(mock_source, StopAecdump()).Times(0);
// Enabling debug recordings should not trigger any calls to the recording
// source.
manager_->EnableDebugRecording(create_file_callback_);
manager_->DisableDebugRecording();
manager_->RegisterAecdumpSource(&mock_source);
base::RunLoop().RunUntilIdle();
manager_->DeregisterAecdumpSource(&mock_source);
}
TEST_F(AecdumpRecordingManagerTest,
RegisterDeregisterSourceDuringRecordingStartsStopsSource) {
InSequence s;
MockAecdumpRecordingSource mock_source;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(1);
EXPECT_CALL(mock_source, StopAecdump()).Times(1);
manager_->EnableDebugRecording(create_file_callback_);
manager_->RegisterAecdumpSource(&mock_source);
base::RunLoop().RunUntilIdle();
manager_->DeregisterAecdumpSource(&mock_source);
::testing::Mock::VerifyAndClearExpectations(&mock_source);
manager_->DisableDebugRecording();
}
TEST_F(AecdumpRecordingManagerTest,
DeregisterSourceBeforeFileCreationCallbackDoesNotStartSource) {
NiceMock<MockAecdumpRecordingSource> mock_source;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(0);
manager_->RegisterAecdumpSource(&mock_source);
// Enabling debug recordings schedules a StartAecdump() call to the recording
// source.
manager_->EnableDebugRecording(create_file_callback_);
// Deregister the source before StartAecdump() can be called.
manager_->DeregisterAecdumpSource(&mock_source);
// Run the file creation callback. Aecdumps should not be started.
base::RunLoop().RunUntilIdle();
manager_->DisableDebugRecording();
}
TEST_F(AecdumpRecordingManagerTest,
StopRecordingBeforeFileCreationCallbackDoesNotStartSource) {
NiceMock<MockAecdumpRecordingSource> mock_source;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(0);
manager_->RegisterAecdumpSource(&mock_source);
// Enabling debug recordings schedules a StartAecdump() call to the recording
// source.
manager_->EnableDebugRecording(create_file_callback_);
// Stop aecdump recording before StartAecdump() can be called.
manager_->DisableDebugRecording();
// Run the file creation callback. Aecdumps should not be started.
base::RunLoop().RunUntilIdle();
// Clean up.
manager_->DeregisterAecdumpSource(&mock_source);
}
TEST_F(AecdumpRecordingManagerTest,
RestartRecordingBeforeFileCreationCallbackDoesNotStartSourceTwice) {
NiceMock<MockAecdumpRecordingSource> mock_source;
EXPECT_CALL(mock_source, StartAecdump(_)).Times(1);
manager_->RegisterAecdumpSource(&mock_source);
// Enabling debug recordings schedules a StartAecdump() call to the recording
// source.
manager_->EnableDebugRecording(create_file_callback_);
// Restart aecdump recording before StartAecdump() can be called.
manager_->DisableDebugRecording();
manager_->EnableDebugRecording(create_file_callback_);
// Run the file creation callback. The first file created should be discarded,
// we expect only one StartAecdump() call.
base::RunLoop().RunUntilIdle();
// Clean up.
manager_->DeregisterAecdumpSource(&mock_source);
manager_->DisableDebugRecording();
}
TEST_F(AecdumpRecordingManagerTest,
DestroyManagerBeforeFileCreationCallbackDoesNotCrash) {
NiceMock<MockAecdumpRecordingSource> mock_source;
manager_->RegisterAecdumpSource(&mock_source);
// Enabling debug recordings schedules a StartAecdump() call to the recording
// source.
manager_->EnableDebugRecording(create_file_callback_);
// Destroy the AecdumpRecordingManager before StartAecdump() can be called.
manager_->DeregisterAecdumpSource(&mock_source);
manager_->DisableDebugRecording();
manager_.reset();
// Run the file creation callback. Aecdumps should not be started.
base::RunLoop().RunUntilIdle();
}
} // namespace
} // namespace media