// 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 cmd_buf = MsdImgAbiBuffer(MsdImgBuffer::Create(kBufferSize, "cmd-buf"));
		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());

		void* mapped_cpu_addr;
		ASSERT_TRUE(cmd_buf.base_ptr()->platform_buffer()->MapCpu(&mapped_cpu_addr));
		auto system_buf = reinterpret_cast<magma_system_command_buffer*>(mapped_cpu_addr);

		msd_buffer_t* exec_resources[3] = { &payload_buf, &additional_buf };
		msd_semaphore_t* semaphore_resources[2] = { &normal_semaphore, &additional_semaphore };

		PVRSRV_BRIDGE_PACKAGE package;
		volatile FuchsiaImgCommandPayload* payload;
		std::vector<std::shared_ptr<MsdImgSemaphore>> semaphores;

		// Need at least 1 resource
		system_buf->num_resources = 0;
		EXPECT_EQ(MAGMA_STATUS_INVALID_ARGS,
			  connection.ProcessCommandBuffer(&cmd_buf, exec_resources, semaphore_resources, &package, &payload,
							  &semaphores));
		EXPECT_FALSE(connection.payload_buffer_);

		system_buf->num_resources = 1;
		system_buf->signal_semaphore_count = 1;

		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(&cmd_buf, exec_resources, 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(&cmd_buf, exec_resources, 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;

		system_buf->signal_semaphore_count = 0;

		// Not enough signal semaphores
		EXPECT_EQ(MAGMA_STATUS_INVALID_ARGS,
			  connection.ProcessCommandBuffer(&cmd_buf, exec_resources, semaphore_resources, &package, &payload,
							  &semaphores));

		system_buf->signal_semaphore_count = 1;
		EXPECT_EQ(MAGMA_STATUS_OK, connection.ProcessCommandBuffer(&cmd_buf, exec_resources, 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.
		system_buf->num_resources = 2;
		semaphores.resize(0);
		// Last semaphore should be used as an additional semaphore
		system_buf->signal_semaphore_count = 2;
		EXPECT_EQ(MAGMA_STATUS_OK, connection.ProcessCommandBuffer(&cmd_buf, exec_resources, 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(); }
