blob: 499d54184b30dd811a18c77d5494566c32b80fb5 [file] [log] [blame]
// Copyright 2019 The Fuchsia 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 "msd_img_connection.h"
#include "gtest/gtest.h"
#include "include/fuchsia_communication.h"
#include "msd_img_buffer.h"
#include "msd_img_semaphore.h"
#include "pvr_bridge.h"
namespace
{
class FakeOwner : public MsdImgConnection::Owner
{
PVRSRV_DEVICE_NODE* device_node() override { return nullptr; }
};
} // namespace
class TestMsdImgConnection
{
public:
static void ProcessBuffer()
{
FakeOwner owner;
MsdImgConnection connection(&owner, 1);
constexpr uint32_t kBufferSize = 4096;
auto payload_buf = MsdImgAbiBuffer(MsdImgBuffer::Create(kBufferSize, "payload"));
auto additional_buf = MsdImgAbiBuffer(MsdImgBuffer::Create(kBufferSize, "array"));
auto normal_semaphore = MsdImgAbiSemaphore(MsdImgSemaphore::Create());
auto additional_semaphore = MsdImgAbiSemaphore(MsdImgSemaphore::Create());
magma_system_command_buffer command_buffer;
msd_buffer_t* buffers[3] = { &payload_buf, &additional_buf };
msd_semaphore_t* semaphore_resources[2] = { &normal_semaphore, &additional_semaphore };
// Exec resource doesn't really matter.
magma_system_exec_resource exec_resource[1] = {};
PVRSRV_BRIDGE_PACKAGE package;
volatile FuchsiaImgCommandPayload* payload;
std::vector<std::shared_ptr<MsdImgSemaphore>> semaphores;
// Need at least 1 resource
command_buffer.num_resources = 0;
EXPECT_EQ(MAGMA_STATUS_INVALID_ARGS,
connection.ProcessCommandBuffer(&command_buffer, exec_resource, buffers, semaphore_resources,
&package, &payload, &semaphores));
EXPECT_FALSE(connection.payload_buffer_);
command_buffer.num_resources = 1;
command_buffer.signal_semaphore_count = 1;
void* mapped_cpu_addr;
ASSERT_TRUE(payload_buf.base_ptr()->platform_buffer()->MapCpu(&mapped_cpu_addr));
auto payload_buf_data = reinterpret_cast<FuchsiaImgCommandPayload*>(mapped_cpu_addr);
constexpr uint32_t kValidDataSize = kBufferSize - sizeof(*payload_buf_data);
// in_data_size is larger than payload, &semaphores buffer.
payload_buf_data->in_data_size = kValidDataSize + 1;
EXPECT_EQ(MAGMA_STATUS_INVALID_ARGS,
connection.ProcessCommandBuffer(&command_buffer, exec_resource, buffers, semaphore_resources,
&package, &payload, &semaphores));
EXPECT_FALSE(connection.payload_buffer_);
// in_data_size is way larger than payload, &semaphores buffer and could cause overflow.
payload_buf_data->in_data_size = 0xffffffff;
EXPECT_EQ(MAGMA_STATUS_INVALID_ARGS,
connection.ProcessCommandBuffer(&command_buffer, exec_resource, buffers, semaphore_resources,
&package, &payload, &semaphores));
EXPECT_FALSE(connection.payload_buffer_);
constexpr uint64_t kThreadId = 0x8765432187654321ul;
payload_buf_data->thread_id = kThreadId;
payload_buf_data->bridge_group = 1;
payload_buf_data->function_id = 2;
payload_buf_data->in_data_size = kValidDataSize;
payload_buf_data->out_data_size = kValidDataSize;
command_buffer.signal_semaphore_count = 0;
// Not enough signal semaphores
EXPECT_EQ(MAGMA_STATUS_INVALID_ARGS,
connection.ProcessCommandBuffer(&command_buffer, exec_resource, buffers, semaphore_resources,
&package, &payload, &semaphores));
command_buffer.signal_semaphore_count = 1;
EXPECT_EQ(MAGMA_STATUS_OK,
connection.ProcessCommandBuffer(&command_buffer, exec_resource, buffers, semaphore_resources,
&package, &payload, &semaphores));
EXPECT_EQ(kThreadId, connection.current_client_thread_id_);
EXPECT_EQ(1u, package.ui32BridgeID);
EXPECT_EQ(2u, package.ui32FunctionID);
EXPECT_EQ(sizeof(package), package.ui32Size);
EXPECT_EQ(kValidDataSize, package.ui32InBufferSize);
EXPECT_EQ(kValidDataSize, package.ui32OutBufferSize);
EXPECT_EQ(payload_buf_data + 1, package.pvParamIn);
EXPECT_EQ(payload_buf_data + 1, package.pvParamOut);
EXPECT_EQ(payload_buf_data, payload);
EXPECT_EQ(payload_buf.base_ptr(), connection.payload_buffer_);
EXPECT_EQ(nullptr, connection.TakeAdditionalBuffer());
EXPECT_EQ(nullptr, connection.TakeAdditionalSemaphore());
EXPECT_EQ(1u, semaphores.size());
// Unmap to test whether the buffer was mapped persistently.
ASSERT_TRUE(payload_buf.base_ptr()->platform_buffer()->UnmapCpu());
connection.payload_buffer_ = nullptr;
// 2 resources are given, so the last should be used as the
// additional buffer.
command_buffer.num_resources = 2;
semaphores.resize(0);
// Last semaphore should be used as an additional semaphore
command_buffer.signal_semaphore_count = 2;
EXPECT_EQ(MAGMA_STATUS_OK,
connection.ProcessCommandBuffer(&command_buffer, exec_resource, buffers, semaphore_resources,
&package, &payload, &semaphores));
EXPECT_EQ(1u, semaphores.size());
EXPECT_EQ(additional_buf.base_ptr(), connection.TakeAdditionalBuffer());
EXPECT_EQ(nullptr, connection.TakeAdditionalBuffer());
EXPECT_EQ(additional_semaphore.base_ptr(), connection.TakeAdditionalSemaphore());
EXPECT_EQ(nullptr, connection.TakeAdditionalSemaphore());
// The parameters should be at the same address because the
// buffer has a persistent mapping.
EXPECT_EQ(payload_buf_data + 1, package.pvParamIn);
connection.CleanupAfterCommand(payload, semaphores, true);
EXPECT_EQ(1u, payload->finished_command);
EXPECT_FALSE(connection.payload_buffer_);
EXPECT_FALSE(connection.additional_buffer_);
EXPECT_FALSE(connection.additional_semaphore_);
EXPECT_EQ(1u, payload->success);
EXPECT_EQ(MAGMA_STATUS_OK, normal_semaphore.base_ptr()->platform_semaphore()->Wait(0u).get());
connection.CleanupAfterCommand(payload, semaphores, false);
EXPECT_EQ(0u, payload->success);
EXPECT_EQ(MAGMA_STATUS_OK, normal_semaphore.base_ptr()->platform_semaphore()->Wait(0u).get());
}
};
TEST(Connection, ProcessBuffer) { TestMsdImgConnection::ProcessBuffer(); }