android13/hardware/google/camera/common/hal/tests/process_block_tests.cc

262 lines
9.1 KiB
C++

/*
* Copyright (C) 2019 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define LOG_TAG "ProcessBlockTest"
#include <log/log.h>
#include <gtest/gtest.h>
#include <memory>
#include "mock_device_session_hwl.h"
#include "mock_result_processor.h"
#include "multicam_realtime_process_block.h"
#include "realtime_process_block.h"
#include "test_utils.h"
using ::testing::_;
namespace android {
namespace google_camera_hal {
// Setup for testing a process block.
struct ProcessBlockTestSetup {
// Function to create a process block.
std::function<std::unique_ptr<ProcessBlock>()> process_block_create_func;
uint32_t camera_id; // Camera ID to test
std::vector<uint32_t> physical_camera_ids; // Physical camera IDs to test.
};
class ProcessBlockTest : public ::testing::Test {
protected:
void SetUp() override {
// Initialize all process block test setups.
realtime_process_block_setup_ = {
.process_block_create_func =
[&]() { return RealtimeProcessBlock::Create(session_hwl_.get()); },
.camera_id = 3,
};
multi_camera_process_block_setup_ = {
.process_block_create_func =
[&]() {
return MultiCameraRtProcessBlock::Create(session_hwl_.get());
},
.camera_id = 3,
.physical_camera_ids = {1, 5},
};
process_block_test_setups_ = {
realtime_process_block_setup_,
multi_camera_process_block_setup_,
};
}
// Create a mock device session HWL and stream configuration based on
// the test setup.
void InitializeProcessBlockTest(const ProcessBlockTestSetup& setup) {
// Create a mock session HWL.
session_hwl_ = std::make_unique<MockDeviceSessionHwl>(
setup.camera_id, setup.physical_camera_ids);
ASSERT_NE(session_hwl_, nullptr);
session_hwl_->DelegateCallsToFakeSession();
// Create a stream configuration for testing.
if (setup.physical_camera_ids.empty()) {
test_utils::GetPreviewOnlyStreamConfiguration(&test_config_);
} else {
test_utils::GetPhysicalPreviewStreamConfiguration(
&test_config_, setup.physical_camera_ids);
}
}
std::unique_ptr<MockDeviceSessionHwl> session_hwl_;
std::vector<ProcessBlockTestSetup> process_block_test_setups_;
ProcessBlockTestSetup realtime_process_block_setup_;
ProcessBlockTestSetup multi_camera_process_block_setup_;
StreamConfiguration test_config_; // Configuration used in tests.
};
TEST_F(ProcessBlockTest, Create) {
for (auto& setup : process_block_test_setups_) {
InitializeProcessBlockTest(setup);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating a process block failed";
}
}
TEST_F(ProcessBlockTest, StreamConfiguration) {
for (auto& setup : process_block_test_setups_) {
InitializeProcessBlockTest(setup);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating a process block failed";
ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
// Configuring stream again should return ALREADY_EXISTS
ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_),
ALREADY_EXISTS);
}
}
TEST_F(ProcessBlockTest, SetResultProcessor) {
for (auto& setup : process_block_test_setups_) {
InitializeProcessBlockTest(setup);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating a process block failed";
ASSERT_EQ(block->SetResultProcessor(nullptr), BAD_VALUE)
<< "Setting a nullptr result processor should return BAD_VALUE";
ASSERT_EQ(
block->SetResultProcessor(std::make_unique<MockResultProcessor>()), OK);
ASSERT_EQ(block->SetResultProcessor(std::make_unique<MockResultProcessor>()),
ALREADY_EXISTS)
<< "Setting result processor again should return ALREADY_EXISTS";
}
}
TEST_F(ProcessBlockTest, GetConfiguredHalStreams) {
for (auto& setup : process_block_test_setups_) {
InitializeProcessBlockTest(setup);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating a process block failed";
ASSERT_EQ(block->GetConfiguredHalStreams(nullptr), BAD_VALUE)
<< "Passing nullptr should return BAD_VALUE";
std::vector<HalStream> hal_streams;
ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), NO_INIT)
<< "Should return NO_INIT without ConfigureStreams()";
ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
ASSERT_EQ(session_hwl_->BuildPipelines(), OK);
ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), OK);
ASSERT_EQ(hal_streams.size(), test_config_.streams.size());
}
}
TEST_F(ProcessBlockTest, Flush) {
for (auto& setup : process_block_test_setups_) {
InitializeProcessBlockTest(setup);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating a process block failed";
ASSERT_EQ(block->Flush(), OK);
ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
ASSERT_EQ(block->Flush(), OK);
}
}
TEST_F(ProcessBlockTest, RealtimeProcessBlockRequest) {
ProcessBlockTestSetup& setup = realtime_process_block_setup_;
InitializeProcessBlockTest(setup);
// Verify process block calls HWL session.
EXPECT_CALL(*session_hwl_, ConfigurePipeline(_, _, _, _, _)).Times(1);
EXPECT_CALL(*session_hwl_, GetConfiguredHalStream(_, _))
.Times(test_config_.streams.size());
EXPECT_CALL(*session_hwl_, SubmitRequests(_, _)).Times(1);
auto result_processor = std::make_unique<MockResultProcessor>();
ASSERT_NE(result_processor, nullptr) << "Cannot create a MockResultProcessor";
// Verify process block calls result processor
EXPECT_CALL(*result_processor, AddPendingRequests(_, _)).Times(1);
EXPECT_CALL(*result_processor, ProcessResult(_)).Times(1);
EXPECT_CALL(*result_processor, Notify(_)).Times(1);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating RealtimeProcessBlock failed";
ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
ASSERT_EQ(session_hwl_->BuildPipelines(), OK);
std::vector<HalStream> hal_streams;
ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), OK);
EXPECT_EQ(hal_streams.size(), test_config_.streams.size());
ASSERT_EQ(block->SetResultProcessor(std::move(result_processor)), OK);
// Testing RealtimeProcessBlock with a dummy request.
std::vector<ProcessBlockRequest> block_requests(1);
ASSERT_EQ(block->ProcessRequests(block_requests, block_requests[0].request),
OK);
}
TEST_F(ProcessBlockTest, MultiCameraRtProcessBlockRequest) {
ProcessBlockTestSetup& setup = multi_camera_process_block_setup_;
InitializeProcessBlockTest(setup);
size_t num_pipelines = setup.physical_camera_ids.size();
size_t num_streams = test_config_.streams.size();
// Verify process block calls HWL session.
EXPECT_CALL(*session_hwl_, ConfigurePipeline(_, _, _, _, _))
.Times(num_pipelines);
EXPECT_CALL(*session_hwl_, GetConfiguredHalStream(_, _)).Times(num_streams);
EXPECT_CALL(*session_hwl_, SubmitRequests(_, _)).Times(1);
auto result_processor = std::make_unique<MockResultProcessor>();
ASSERT_NE(result_processor, nullptr) << "Cannot create a MockResultProcessor";
// Verify process block calls result processor
EXPECT_CALL(*result_processor, AddPendingRequests(_, _)).Times(1);
EXPECT_CALL(*result_processor, ProcessResult(_)).Times(num_pipelines);
EXPECT_CALL(*result_processor, Notify(_)).Times(num_pipelines);
auto block = setup.process_block_create_func();
ASSERT_NE(block, nullptr) << "Creating MultiCameraRtProcessBlock failed";
ASSERT_EQ(block->ConfigureStreams(test_config_, test_config_), OK);
ASSERT_EQ(session_hwl_->BuildPipelines(), OK);
std::vector<HalStream> hal_streams;
ASSERT_EQ(block->GetConfiguredHalStreams(&hal_streams), OK);
EXPECT_EQ(hal_streams.size(), test_config_.streams.size());
ASSERT_EQ(block->SetResultProcessor(std::move(result_processor)), OK);
// Testing RealtimeProcessBlock with dummy requests.
std::vector<ProcessBlockRequest> block_requests;
CaptureRequest remaining_session_requests;
for (auto& stream : test_config_.streams) {
StreamBuffer buffer;
buffer.stream_id = stream.id;
ProcessBlockRequest block_request;
block_request.request.output_buffers.push_back(buffer);
block_requests.push_back(std::move(block_request));
remaining_session_requests.output_buffers.push_back(buffer);
}
ASSERT_EQ(block->ProcessRequests(block_requests, remaining_session_requests),
OK);
}
} // namespace google_camera_hal
} // namespace android