blob: 09d673bb4fef24829d7c2a8d8d72fbeca74a11e8 [file]
/*
* Copyright (C) 2025 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 <gtest/gtest.h>
#include <gui/RenderCommandBuffer.h>
#include <cstring>
#include <memory>
#include <vector>
namespace android {
TEST(RenderCommandBufferTest, RPointerBehavesCorrectlyWhenCopied) {
struct TestStruct {
int data;
RPointer<int> pointer;
};
TestStruct structOriginal;
structOriginal.data = 42;
structOriginal.pointer = &structOriginal.data;
// Verify the pointer in the original struct.
ASSERT_EQ(&structOriginal.data, structOriginal.pointer.get());
ASSERT_EQ(42, *structOriginal.pointer);
// Create a copy.
TestStruct structCopy = structOriginal;
// Verify that the copy's pointer points to the copy's data, not the original's.
ASSERT_NE(&structOriginal.data, structCopy.pointer.get());
ASSERT_EQ(&structCopy.data, structCopy.pointer.get());
ASSERT_EQ(42, *structCopy.pointer);
// Modify the copy's data and check if the pointer reflects the change.
structCopy.data = 99;
ASSERT_EQ(99, *structCopy.pointer);
// Ensure the original struct is unchanged.
ASSERT_EQ(42, structOriginal.data);
ASSERT_EQ(42, *structOriginal.pointer);
}
TEST(RenderCommandBufferTest, AllocAndPushOp) {
auto bufferOriginal = std::make_unique<RenderCommandBuffer>();
ASSERT_NE(nullptr, bufferOriginal.get());
auto* opOriginal = bufferOriginal->allocAligned<IPCRenderBufferOp>();
ASSERT_NE(nullptr, opOriginal);
opOriginal->type = 1;
bufferOriginal->pushOp(opOriginal);
auto bufferCopy = std::make_unique<RenderCommandBuffer>();
memcpy(bufferCopy.get(), bufferOriginal.get(), sizeof(RenderCommandBuffer));
IPCRenderBufferOp* opCopy = bufferCopy->getOps();
ASSERT_NE(nullptr, opCopy);
// the copy should have different address but same value
ASSERT_NE(opOriginal, opCopy);
ASSERT_EQ(opOriginal->type, opCopy->type);
}
TEST(RenderCommandBufferTest, PushMultipleOps) {
auto bufferOriginal = std::make_unique<RenderCommandBuffer>();
ASSERT_NE(nullptr, bufferOriginal.get());
constexpr unsigned int opCount = 3;
IPCRenderBufferOp* opsOriginal[opCount];
for (unsigned int i = 0; i < opCount; i++) {
opsOriginal[i] = bufferOriginal->allocAligned<IPCRenderBufferOp>();
ASSERT_NE(nullptr, opsOriginal[i]);
opsOriginal[i]->type = i;
bufferOriginal->pushOp(opsOriginal[i]);
}
auto bufferCopy = std::make_unique<RenderCommandBuffer>();
memcpy(bufferCopy.get(), bufferOriginal.get(), sizeof(RenderCommandBuffer));
IPCRenderBufferOp* opCopy = bufferCopy->getOps();
for (unsigned int i = 0; i < opCount; i++) {
const auto* opOriginal = opsOriginal[i];
ASSERT_NE(nullptr, opCopy);
// the copy should have different address but same value
ASSERT_NE(opOriginal, opCopy);
ASSERT_EQ(opOriginal->type, opCopy->type);
opCopy = opCopy->next;
}
ASSERT_EQ(nullptr, opCopy);
}
TEST(RenderCommandBufferTest, PushMultipleOpsWithData) {
auto bufferOriginal = std::make_unique<RenderCommandBuffer>();
ASSERT_NE(nullptr, bufferOriginal.get());
struct TestOp : public IPCRenderBufferOp {
RSpan<int> data;
};
constexpr unsigned int opCount = 3;
TestOp* opsOriginal[opCount];
std::vector<std::vector<int>> testData(opCount);
for (unsigned int i = 0; i < opCount; i++) {
TestOp* op = bufferOriginal->allocAligned<TestOp>();
ASSERT_NE(nullptr, op);
opsOriginal[i] = op;
op->type = i;
std::vector<int>& td = testData[i];
td.resize(5 + i * 5);
for (size_t j = 0; j < td.size(); j++) {
td[j] = i * 10 + j;
}
ASSERT_TRUE(SetRSpan(op->data, bufferOriginal.get(), td.data(), td.size()));
bufferOriginal->pushOp(op);
}
auto bufferCopy = std::make_unique<RenderCommandBuffer>();
memcpy(bufferCopy.get(), bufferOriginal.get(), sizeof(RenderCommandBuffer));
IPCRenderBufferOp* opCopy = bufferCopy->getOps();
for (unsigned int i = 0; i < opCount; i++) {
const auto* opOriginal = opsOriginal[i];
ASSERT_NE(nullptr, opCopy);
ASSERT_NE(opOriginal, opCopy);
ASSERT_EQ(opOriginal->type, opCopy->type);
TestOp* testOpCopy = static_cast<TestOp*>(opCopy);
std::vector<int>& td = testData[i];
ASSERT_EQ(td.size(), testOpCopy->data.size);
ASSERT_EQ(0, memcmp(td.data(), testOpCopy->data.data.get(), td.size() * sizeof(int)));
opCopy = opCopy->next;
}
ASSERT_EQ(nullptr, opCopy);
}
} // namespace android