blob: a68ff57f5b72d5d73b8a72dad736ad32512c6da9 [file] [log] [blame]
/*
* Copyright (C) 2016 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.
*/
#include "request_tracker.h"
#include <gmock/gmock.h>
#include <gtest/gtest.h>
using testing::AtMost;
using testing::Expectation;
using testing::Return;
using testing::SetArgPointee;
using testing::Test;
using testing::_;
namespace default_camera_hal {
class RequestTrackerTest : public Test {
protected:
void SetUp() {
stream1_.max_buffers = 3;
stream2_.max_buffers = 3;
dut_.reset(new RequestTracker());
streams_ = {&stream1_, &stream2_};
camera3_stream_configuration_t config{streams_.size(), streams_.data(), 0};
dut_->SetStreamConfiguration(config);
}
std::shared_ptr<CaptureRequest> GenerateCaptureRequest(
uint32_t frame, std::vector<camera3_stream_t*> streams) {
std::shared_ptr<CaptureRequest> request =
std::make_shared<CaptureRequest>();
// Set the frame number and buffers.
request->frame_number = frame;
for (const auto stream : streams) {
// All we really care about for the buffers is which stream they're for.
camera3_stream_buffer_t buffer{stream, nullptr, 0, -1, -1};
request->output_buffers.push_back(buffer);
}
return request;
}
void AddRequest(uint32_t frame,
std::vector<camera3_stream_t*> streams,
bool expected = true) {
std::shared_ptr<CaptureRequest> request =
GenerateCaptureRequest(frame, streams);
EXPECT_EQ(dut_->CanAddRequest(*request), expected);
if (expected) {
EXPECT_FALSE(dut_->InFlight(frame));
}
EXPECT_EQ(dut_->Add(request), expected);
if (expected) {
EXPECT_TRUE(dut_->InFlight(frame));
}
}
camera3_stream_t stream1_;
camera3_stream_t stream2_;
std::vector<camera3_stream_t*> streams_;
std::shared_ptr<RequestTracker> dut_;
};
TEST_F(RequestTrackerTest, AddValid) {
uint32_t frame = 34;
EXPECT_FALSE(dut_->InFlight(frame));
AddRequest(frame, {&stream1_});
}
TEST_F(RequestTrackerTest, AddInput) {
EXPECT_TRUE(dut_->Empty());
// Add a request
uint32_t frame = 42;
std::shared_ptr<CaptureRequest> expected = GenerateCaptureRequest(frame, {});
// Set the input buffer instead of any outputs.
expected->input_buffer.reset(
new camera3_stream_buffer_t{&stream1_, nullptr, 0, -1, -1});
stream1_.max_buffers = 1;
EXPECT_TRUE(dut_->Add(expected));
EXPECT_TRUE(dut_->InFlight(frame));
// Should have added to the count of buffers for stream 1.
EXPECT_TRUE(dut_->StreamFull(&stream1_));
}
TEST_F(RequestTrackerTest, AddMultipleStreams) {
stream1_.max_buffers = 1;
stream2_.max_buffers = 1;
EXPECT_FALSE(dut_->StreamFull(&stream1_));
EXPECT_FALSE(dut_->StreamFull(&stream2_));
// Add a request using both streams.
AddRequest(99, {&stream1_, &stream2_});
// Should both have been counted.
EXPECT_TRUE(dut_->StreamFull(&stream1_));
EXPECT_TRUE(dut_->StreamFull(&stream2_));
}
TEST_F(RequestTrackerTest, AddUnconfigured) {
camera3_stream_t stream;
// Unconfigured should be considered full.
EXPECT_TRUE(dut_->StreamFull(&stream));
AddRequest(1, {&stream}, false);
}
TEST_F(RequestTrackerTest, AddPastCapacity) {
// Set the limit of stream 2 to 1.
stream2_.max_buffers = 1;
for (size_t i = 0; i < stream1_.max_buffers; ++i) {
EXPECT_FALSE(dut_->StreamFull(&stream1_));
EXPECT_FALSE(dut_->StreamFull(&stream2_));
AddRequest(i, {&stream1_});
}
// Filled up stream 1.
EXPECT_TRUE(dut_->StreamFull(&stream1_));
// Stream 2 should still not be full since nothing was added.
EXPECT_FALSE(dut_->StreamFull(&stream2_));
// Limit has been hit, can't add more.
AddRequest(stream1_.max_buffers, {&stream1_, &stream2_}, false);
EXPECT_TRUE(dut_->StreamFull(&stream1_));
// Should not have added to the count of stream 2.
EXPECT_FALSE(dut_->StreamFull(&stream2_));
}
TEST_F(RequestTrackerTest, AddDuplicate) {
uint32_t frame = 42;
AddRequest(frame, {&stream1_});
// Can't add a duplicate.
AddRequest(frame, {&stream2_}, false);
}
TEST_F(RequestTrackerTest, RemoveValid) {
EXPECT_TRUE(dut_->Empty());
// Add a request
uint32_t frame = 42;
std::shared_ptr<CaptureRequest> request =
GenerateCaptureRequest(frame, {&stream1_});
EXPECT_TRUE(dut_->Add(request));
EXPECT_TRUE(dut_->InFlight(frame));
AddRequest(frame + 1, {&stream1_});
EXPECT_FALSE(dut_->Empty());
// Remove it.
EXPECT_TRUE(dut_->Remove(request));
// Should have removed only the desired request.
EXPECT_FALSE(dut_->Empty());
}
TEST_F(RequestTrackerTest, RemoveInvalidFrame) {
EXPECT_TRUE(dut_->Empty());
// Add a request
uint32_t frame = 42;
AddRequest(frame, {&stream1_});
EXPECT_FALSE(dut_->Empty());
// Try to remove a different one.
uint32_t bad_frame = frame + 1;
std::shared_ptr<CaptureRequest> bad_request =
GenerateCaptureRequest(bad_frame, {&stream1_});
EXPECT_FALSE(dut_->InFlight(bad_frame));
EXPECT_FALSE(dut_->Remove(bad_request));
EXPECT_FALSE(dut_->Empty());
}
TEST_F(RequestTrackerTest, RemoveInvalidData) {
EXPECT_TRUE(dut_->Empty());
// Add a request
uint32_t frame = 42;
AddRequest(frame, {&stream1_});
EXPECT_FALSE(dut_->Empty());
// Try to remove a different one.
// Even though this request looks the same, that fact that it is
// a pointer to a different object means it should fail.
std::shared_ptr<CaptureRequest> bad_request =
GenerateCaptureRequest(frame, {&stream1_});
EXPECT_TRUE(dut_->InFlight(frame));
EXPECT_FALSE(dut_->Remove(bad_request));
EXPECT_FALSE(dut_->Empty());
}
TEST_F(RequestTrackerTest, RemoveNull) {
EXPECT_FALSE(dut_->Remove(nullptr));
}
TEST_F(RequestTrackerTest, ClearRequests) {
// Create some requests.
uint32_t frame1 = 42;
uint32_t frame2 = frame1 + 1;
std::shared_ptr<CaptureRequest> request1 =
GenerateCaptureRequest(frame1, {&stream1_});
std::shared_ptr<CaptureRequest> request2 =
GenerateCaptureRequest(frame2, {&stream2_});
std::set<std::shared_ptr<CaptureRequest>> expected;
expected.insert(request1);
expected.insert(request2);
// Insert them.
EXPECT_TRUE(dut_->Add(request1));
EXPECT_TRUE(dut_->Add(request2));
EXPECT_TRUE(dut_->InFlight(frame1));
EXPECT_TRUE(dut_->InFlight(frame2));
EXPECT_FALSE(dut_->Empty());
std::set<std::shared_ptr<CaptureRequest>> actual;
// Clear them out.
dut_->Clear(&actual);
EXPECT_TRUE(dut_->Empty());
EXPECT_EQ(actual, expected);
// Configuration (max values) should not have been cleared.
EXPECT_TRUE(dut_->Add(request1));
}
TEST_F(RequestTrackerTest, ClearRequestsNoResult) {
// Add some requests.
EXPECT_TRUE(dut_->Empty());
AddRequest(1, {&stream1_});
AddRequest(2, {&stream2_});
EXPECT_FALSE(dut_->Empty());
// Don't bother getting the cleared requests.
dut_->Clear();
EXPECT_TRUE(dut_->Empty());
}
TEST_F(RequestTrackerTest, ClearConfiguration) {
EXPECT_FALSE(dut_->StreamFull(&stream1_));
EXPECT_FALSE(dut_->StreamFull(&stream2_));
// Clear the configuration.
dut_->ClearStreamConfiguration();
// Both streams should be considered full now, since neither is configured.
EXPECT_TRUE(dut_->StreamFull(&stream1_));
EXPECT_TRUE(dut_->StreamFull(&stream2_));
}
} // namespace default_camera_hal