blob: 4b51ed899d08a282565be74a77b9a85b2d53a293 [file] [log] [blame]
// Copyright 2016 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 <fcntl.h>
#include <poll.h>
#include "magma.h"
#include "magma_util/dlog.h"
#include "magma_util/macros.h"
#include "platform_buffer.h"
#include "gtest/gtest.h"
#include <thread>
extern "C" {
#include "test_magma_abi.h"
}
class TestConnection {
public:
TestConnection()
{
fd_ = open("/dev/class/gpu/000", O_RDONLY);
DASSERT(fd_ >= 0);
magma_create_connection(fd(), &connection_);
}
~TestConnection()
{
if (connection_)
magma_release_connection(connection_);
close(fd_);
}
int fd() { return fd_; }
void GetDeviceId()
{
uint64_t device_id = 0;
EXPECT_EQ(MAGMA_STATUS_OK, magma_query(fd_, MAGMA_QUERY_DEVICE_ID, &device_id));
EXPECT_NE(0u, device_id);
}
magma_connection_t connection() { return connection_; }
void Connection() { ASSERT_NE(connection_, nullptr); }
void Context()
{
ASSERT_NE(connection_, nullptr);
uint32_t context_id[2];
magma_create_context(connection_, &context_id[0]);
EXPECT_EQ(magma_get_error(connection_), 0);
magma_create_context(connection_, &context_id[1]);
EXPECT_EQ(magma_get_error(connection_), 0);
magma_release_context(connection_, context_id[0]);
EXPECT_EQ(magma_get_error(connection_), 0);
magma_release_context(connection_, context_id[1]);
EXPECT_EQ(magma_get_error(connection_), 0);
magma_release_context(connection_, context_id[1]);
EXPECT_NE(magma_get_error(connection_), 0);
}
void NotificationFd()
{
int fd1 = magma_get_notification_channel_fd(connection_);
EXPECT_LE(0, fd1);
int fd2 = magma_get_notification_channel_fd(connection_);
EXPECT_LE(0, fd1);
EXPECT_NE(fd1, fd2);
struct pollfd fds[2] = {{fd1, POLLIN, 0}, {fd2, POLLOUT, 0}};
int result = poll(fds, 2, 0);
// No events should exist.
EXPECT_EQ(0, result);
EXPECT_EQ(0, fds[0].revents);
EXPECT_EQ(0, fds[1].revents);
close(fd1);
close(fd2);
}
void NotificationChannel()
{
uint32_t handle = magma_get_notification_channel_handle(connection_);
EXPECT_NE(0u, handle);
uint32_t handle2 = magma_get_notification_channel_handle(connection_);
EXPECT_EQ(handle, handle2);
}
void Buffer()
{
ASSERT_NE(connection_, nullptr);
uint64_t size = PAGE_SIZE;
uint64_t actual_size;
uint64_t id;
EXPECT_EQ(magma_create_buffer(connection_, size, &actual_size, &id), 0);
EXPECT_GE(size, actual_size);
EXPECT_NE(id, 0u);
magma_release_buffer(connection_, id);
}
void BufferMap()
{
ASSERT_NE(connection_, nullptr);
uint64_t size = PAGE_SIZE;
uint64_t actual_size;
uint64_t id;
EXPECT_EQ(magma_create_buffer(connection_, size, &actual_size, &id), 0);
EXPECT_NE(id, 0u);
magma_map_buffer_gpu(connection_, id, 1024, 0, size / PAGE_SIZE, MAGMA_GPU_MAP_FLAG_READ);
magma_unmap_buffer_gpu(connection_, id, 2048);
magma_commit_buffer(connection_, id, 100, 100);
magma_release_buffer(connection_, id);
}
void BufferExport(uint32_t* handle_out, uint64_t* id_out)
{
ASSERT_NE(connection_, nullptr);
uint64_t size = PAGE_SIZE;
magma_buffer_t buffer;
EXPECT_EQ(magma_create_buffer(connection_, size, &size, &buffer), 0);
*id_out = magma_get_buffer_id(buffer);
EXPECT_EQ(magma_export(connection_, buffer, handle_out), 0);
}
void BufferImport(uint32_t handle, uint64_t id)
{
ASSERT_NE(connection_, nullptr);
magma_buffer_t buffer;
EXPECT_EQ(magma_import(connection_, handle, &buffer), 0);
EXPECT_EQ(magma_get_buffer_id(buffer), id);
}
static void BufferImportExport(TestConnection* test1, TestConnection* test2)
{
uint32_t handle;
uint64_t id;
test1->BufferExport(&handle, &id);
test2->BufferImport(handle, id);
}
void Semaphore(uint32_t count)
{
ASSERT_NE(connection_, nullptr);
std::vector<magma_semaphore_t> semaphore(count);
for (uint32_t i = 0; i < count; i++) {
EXPECT_EQ(MAGMA_STATUS_OK, magma_create_semaphore(connection_, &semaphore[i]));
EXPECT_NE(0u, magma_get_semaphore_id(semaphore[i]));
}
auto thread = std::thread([semaphore, wait_all = true] {
EXPECT_EQ(MAGMA_STATUS_OK, magma_wait_semaphores(semaphore.data(), semaphore.size(),
UINT64_MAX, wait_all));
for (uint32_t i = 0; i < semaphore.size(); i++) {
magma_reset_semaphore(semaphore[i]);
}
EXPECT_EQ(MAGMA_STATUS_TIMED_OUT,
magma_wait_semaphores(semaphore.data(), semaphore.size(), 100, wait_all));
});
for (uint32_t i = 0; i < semaphore.size(); i++) {
usleep(10 * 1000);
magma_signal_semaphore(semaphore[i]);
}
thread.join();
thread = std::thread([semaphore, wait_all = false] {
EXPECT_EQ(MAGMA_STATUS_OK, magma_wait_semaphores(semaphore.data(), semaphore.size(),
UINT64_MAX, wait_all));
for (uint32_t i = 0; i < semaphore.size(); i++) {
magma_reset_semaphore(semaphore[i]);
}
EXPECT_EQ(MAGMA_STATUS_TIMED_OUT,
magma_wait_semaphores(semaphore.data(), semaphore.size(), 100, wait_all));
});
usleep(10 * 1000);
magma_signal_semaphore(semaphore[semaphore.size() - 1]);
thread.join();
for (uint32_t i = 0; i < semaphore.size(); i++) {
magma_release_semaphore(connection_, semaphore[i]);
}
}
void SemaphoreExport(uint32_t* handle_out, uint64_t* id_out)
{
ASSERT_NE(connection_, nullptr);
magma_semaphore_t semaphore;
EXPECT_EQ(magma_create_semaphore(connection_, &semaphore), MAGMA_STATUS_OK);
*id_out = magma_get_semaphore_id(semaphore);
EXPECT_EQ(magma_export_semaphore(connection_, semaphore, handle_out), MAGMA_STATUS_OK);
}
void SemaphoreImport(uint32_t handle, uint64_t id)
{
ASSERT_NE(connection_, nullptr);
magma_semaphore_t semaphore;
EXPECT_EQ(magma_import_semaphore(connection_, handle, &semaphore), MAGMA_STATUS_OK);
EXPECT_EQ(magma_get_semaphore_id(semaphore), id);
}
static void SemaphoreImportExport(TestConnection* test1, TestConnection* test2)
{
uint32_t handle;
uint64_t id;
test1->SemaphoreExport(&handle, &id);
test2->SemaphoreImport(handle, id);
}
private:
int fd_ = -1;
magma_connection_t connection_;
};
TEST(MagmaAbi, DeviceId)
{
TestConnection test;
test.GetDeviceId();
}
TEST(MagmaAbi, Buffer)
{
TestConnection test;
test.Buffer();
}
TEST(MagmaAbi, Connection)
{
TestConnection test;
test.Connection();
}
TEST(MagmaAbi, Context)
{
TestConnection test;
test.Context();
}
TEST(MagmaAbi, NotificationFd)
{
TestConnection test;
test.NotificationFd();
}
TEST(MagmaAbi, NotificationChannel)
{
TestConnection test;
test.NotificationChannel();
}
TEST(MagmaAbi, BufferMap)
{
TestConnection test;
test.BufferMap();
}
TEST(MagmaAbi, BufferImportExport)
{
TestConnection test1;
TestConnection test2;
TestConnection::BufferImportExport(&test1, &test2);
}
TEST(MagmaAbi, Semaphore)
{
TestConnection test;
test.Semaphore(1);
test.Semaphore(2);
test.Semaphore(3);
}
TEST(MagmaAbi, SemaphoreImportExport)
{
TestConnection test1;
TestConnection test2;
TestConnection::SemaphoreImportExport(&test1, &test2);
}
TEST(MagmaAbi, FromC) { EXPECT_TRUE(test_magma_abi_from_c()); }