// Copyright 2017 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 <limits>

#include "mock/mock_bus_mapper.h"
#include "gtest/gtest.h"

#include "address_manager.h"
#include "gpu_mapping.h"
#include "msd_arm_buffer.h"
#include "msd_arm_connection.h"

namespace {

class TestAddressSpaceObserver : public AddressSpaceObserver {
public:
    void FlushAddressMappingRange(AddressSpace*, uint64_t start, uint64_t length,
                                  bool synchronous) override
    {
    }
    void UnlockAddressSpace(AddressSpace* address_space) override
    {
        unlocked_address_spaces_.push_back(address_space);
    }
    void ReleaseSpaceMappings(const AddressSpace* address_space) override {}

    const std::vector<AddressSpace*>& unlocked_address_spaces() const
    {
        return unlocked_address_spaces_;
    }

private:
    std::vector<AddressSpace*> unlocked_address_spaces_;
};

class FakeConnectionOwner : public MsdArmConnection::Owner {
public:
    FakeConnectionOwner() {}

    void ScheduleAtom(std::shared_ptr<MsdArmAtom> atom) override { atoms_list_.push_back(atom); }
    void CancelAtoms(std::shared_ptr<MsdArmConnection> connection) override
    {
        cancel_atoms_list_.push_back(connection.get());
    }
    AddressSpaceObserver* GetAddressSpaceObserver() override { return &observer_; }
    TestAddressSpaceObserver* GetTestAddressSpaceObserver() { return &observer_; }
    magma::PlatformBusMapper* GetBusMapper() override { return &bus_mapper_; }
    ArmMaliCacheCoherencyStatus cache_coherency_status() override
    {
        return kArmMaliCacheCoherencyAce;
    }

    const std::vector<MsdArmConnection*>& cancel_atoms_list() { return cancel_atoms_list_; }
    const std::vector<std::shared_ptr<MsdArmAtom>>& atoms_list() { return atoms_list_; }

private:
    TestAddressSpaceObserver observer_;
    MockConsistentBusMapper bus_mapper_;
    std::vector<MsdArmConnection*> cancel_atoms_list_;
    std::vector<std::shared_ptr<MsdArmAtom>> atoms_list_;
};

class DeregisterConnectionOwner : public FakeConnectionOwner {
public:
    void set_connection(std::weak_ptr<MsdArmConnection> connection) { connection_ = connection; }
    void DeregisterConnection() override { EXPECT_TRUE(connection_.expired()); }

private:
    std::weak_ptr<MsdArmConnection> connection_;
};

void* g_test_token;
uint32_t g_test_data_size;
magma_arm_mali_status g_status;

void TestCallback(void* token, msd_notification_t* notification)
{
    g_test_token = token;
    if (notification->type == MSD_CONNECTION_NOTIFICATION_CHANNEL_SEND) {
        g_test_data_size = notification->u.channel_send.size;
        memcpy(&g_status, notification->u.channel_send.data, g_test_data_size);
    }
}
} // namespace

class TestConnection {
public:
    void MapUnmap()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = PAGE_SIZE * 100;

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);

        // GPU VA not page aligned
        EXPECT_FALSE(connection->AddMapping(
            std::make_unique<GpuMapping>(1, 0, 1, 0, connection.get(), buffer)));

        // Empty GPU VA.
        EXPECT_FALSE(connection->AddMapping(
            std::make_unique<GpuMapping>(PAGE_SIZE, 0, 0, 0, connection.get(), buffer)));

        // size would overflow.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, 0, std::numeric_limits<uint64_t>::max() - PAGE_SIZE * 100 + 1, 0,
            connection.get(), buffer)));

        // GPU VA would be larger than 48 bits wide.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, 0, (1ul << 48) - 999 * PAGE_SIZE, 0, connection.get(), buffer)));

        // Map is too large for buffer.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, 0, PAGE_SIZE * 101, 0, connection.get(), buffer)));

        // Map is past end of buffer due to offset.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, 1, PAGE_SIZE * 100, 0, connection.get(), buffer)));

        // Page offset would overflow.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, std::numeric_limits<uint64_t>::max() / PAGE_SIZE, PAGE_SIZE * 100, 0,
            connection.get(), buffer)));

        // Invalid flags.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, 0, PAGE_SIZE * 100, (1 << 14), connection.get(), buffer)));

        EXPECT_TRUE(connection->AddMapping(std::make_unique<GpuMapping>(
            1000 * PAGE_SIZE, 0, PAGE_SIZE * 100, 0, connection.get(), buffer)));

        // Mapping would overlap previous mapping.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            1001 * PAGE_SIZE, 0, PAGE_SIZE * 99, 0, connection.get(), buffer)));

        // Mapping would overlap next mapping.
        EXPECT_FALSE(connection->AddMapping(std::make_unique<GpuMapping>(
            999 * PAGE_SIZE, 0, PAGE_SIZE * 100, 0, connection.get(), buffer)));

        EXPECT_TRUE(connection->AddMapping(std::make_unique<GpuMapping>(
            1100 * PAGE_SIZE, 0, PAGE_SIZE * 100, 0, connection.get(), buffer)));

        EXPECT_FALSE(connection->RemoveMapping(1001 * PAGE_SIZE));

        EXPECT_TRUE(connection->RemoveMapping(1000 * PAGE_SIZE));

        buffer.reset();

        // Mapping should already have been removed by buffer deletion.
        EXPECT_FALSE(connection->RemoveMapping(1100 * PAGE_SIZE));
    }

    void CommitMemory()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = PAGE_SIZE * 100;
        AddressSpace* address_space = connection->address_space_for_testing();

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);

        constexpr uint64_t kGpuOffset[] = {1000, 1100};

        auto mapping0 = std::make_unique<GpuMapping>(kGpuOffset[0] * PAGE_SIZE, 1, PAGE_SIZE * 99,
                                                     0, connection.get(), buffer);
        GpuMapping* mapping0_ptr = mapping0.get();
        EXPECT_TRUE(connection->AddMapping(std::move(mapping0)));

        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 1));
        mali_pte_t pte;
        constexpr uint64_t kInvalidPte = 2u;
        // Only the first page should be committed.
        EXPECT_TRUE(address_space->ReadPteForTesting(kGpuOffset[0] * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 1) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);

        // Should be legal to map with pages already committed.
        EXPECT_TRUE(connection->AddMapping(std::make_unique<GpuMapping>(
            kGpuOffset[1] * PAGE_SIZE, 1, PAGE_SIZE * 2, 0, connection.get(), buffer)));

        EXPECT_TRUE(address_space->ReadPteForTesting(kGpuOffset[1] * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);

        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 5));

        ASSERT_EQ(2u, mapping0_ptr->bus_mappings_.size());
        EXPECT_EQ(1u, mapping0_ptr->bus_mappings_[0]->page_count());
        EXPECT_EQ(2u, mapping0_ptr->bus_mappings_[1]->page_offset());
        EXPECT_EQ(4u, mapping0_ptr->bus_mappings_[1]->page_count());

        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[1] + 1) * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);
        // The mapping should be truncated because it's only for 2 pages.
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[1] + 2) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 4) * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);

        EXPECT_TRUE(connection->RemoveMapping(kGpuOffset[1] * PAGE_SIZE));

        // Should unmap the last page.
        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 4));
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 4) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);
        ASSERT_EQ(1u, mapping0_ptr->bus_mappings_.size());
        EXPECT_EQ(1u, mapping0_ptr->bus_mappings_[0]->page_offset());
        EXPECT_EQ(4u, mapping0_ptr->bus_mappings_[0]->page_count());
        EXPECT_EQ(4u, mapping0_ptr->pinned_page_count());

        // Should be ignored because offset isn't supported.
        EXPECT_FALSE(connection->CommitMemoryForBuffer(buffer.get(), 0, 6));
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 4) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);

        // Can decommit entire buffer.
        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 0));
        EXPECT_FALSE(address_space->ReadPteForTesting(kGpuOffset[0] * PAGE_SIZE, &pte));
    }

    void CommitLargeBuffer()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = 1ul << 35; // 32 GB

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);
        MsdArmAbiBuffer abi_buffer(buffer);

        constexpr uint64_t kGpuOffset[] = {1000, 1100};

        EXPECT_TRUE(connection->AddMapping(std::make_unique<GpuMapping>(
            kGpuOffset[0] * PAGE_SIZE, 0, PAGE_SIZE * 100, 0, connection.get(), buffer)));

        // Committing 1 page should be fine.
        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 0, 1));

        // MockBusMapper will fail committing the entire region.
        EXPECT_TRUE(connection->AddMapping(std::make_unique<GpuMapping>(
            kGpuOffset[1] * PAGE_SIZE, 0, kBufferSize, 0, connection.get(), buffer)));

        EXPECT_FALSE(connection->CommitMemoryForBuffer(buffer.get(), 0, kBufferSize / PAGE_SIZE));
    }

    void GrowableMemory()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = PAGE_SIZE * 100;
        AddressSpace* address_space = connection->address_space_for_testing();

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);

        constexpr uint64_t kGpuOffset[] = {1000, 1100};

        EXPECT_TRUE(connection->AddMapping(
            std::make_unique<GpuMapping>(kGpuOffset[0] * PAGE_SIZE, 1, PAGE_SIZE * 95,
                                         MAGMA_GPU_MAP_FLAG_GROWABLE, connection.get(), buffer)));
        EXPECT_TRUE(connection->AddMapping(
            std::make_unique<GpuMapping>(kGpuOffset[1] * PAGE_SIZE, 1, PAGE_SIZE * 95,
                                         MAGMA_GPU_MAP_FLAG_GROWABLE, connection.get(), buffer)));

        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 1));
        mali_pte_t pte;
        constexpr uint64_t kInvalidPte = 2u;
        // Only the first page should be committed.
        EXPECT_TRUE(address_space->ReadPteForTesting(kGpuOffset[0] * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 1) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);

        EXPECT_FALSE(connection->PageInMemory((kGpuOffset[0] + 95) * PAGE_SIZE));

        // Should grow to a 64-page boundary.
        EXPECT_TRUE(connection->PageInMemory((kGpuOffset[0] + 1) * PAGE_SIZE));
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 1) * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 63) * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 64) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);

        // Second mapping should also be grown.
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[1] + 1) * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);

        // Should be growable up to last page of mapping.
        EXPECT_TRUE(connection->PageInMemory((kGpuOffset[0] + 94) * PAGE_SIZE));
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 94) * PAGE_SIZE, &pte));
        EXPECT_NE(kInvalidPte, pte);
        EXPECT_TRUE(address_space->ReadPteForTesting((kGpuOffset[0] + 95) * PAGE_SIZE, &pte));
        EXPECT_EQ(kInvalidPte, pte);

        // Address space size didn't change, so it should be unlocked.
        EXPECT_EQ(0u, owner.GetTestAddressSpaceObserver()->unlocked_address_spaces().size());
        EXPECT_TRUE(connection->PageInMemory((kGpuOffset[0] + 94) * PAGE_SIZE));
        EXPECT_LE(1u, owner.GetTestAddressSpaceObserver()->unlocked_address_spaces().size());
    }

    void Notification()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        MsdArmAtom atom(connection, 0, 1, 5, magma_arm_mali_user_data{7, 8}, 0);

        // Shouldn't do anything.
        connection->SendNotificationData(&atom, static_cast<ArmMaliResultCode>(10));

        uint32_t token;
        connection->SetNotificationCallback(&TestCallback, &token);
        connection->SendNotificationData(&atom, static_cast<ArmMaliResultCode>(20));
        EXPECT_EQ(sizeof(g_status), g_test_data_size);
        EXPECT_EQ(&token, g_test_token);

        EXPECT_EQ(7u, g_status.data.data[0]);
        EXPECT_EQ(8u, g_status.data.data[1]);
        EXPECT_EQ(20u, g_status.result_code);
        EXPECT_EQ(5u, g_status.atom_number);

        connection->SetNotificationCallback(nullptr, nullptr);
        connection->SendNotificationData(&atom, static_cast<ArmMaliResultCode>(20));

        EXPECT_EQ(20u, g_status.result_code);
    }

    void DestructionNotification()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);

        uint32_t token;
        connection->SetNotificationCallback(&TestCallback, &token);
        connection->MarkDestroyed();

        EXPECT_EQ(sizeof(g_status), g_test_data_size);
        EXPECT_EQ(&token, g_test_token);

        EXPECT_EQ(0u, g_status.data.data[0]);
        EXPECT_EQ(0u, g_status.data.data[1]);
        EXPECT_EQ(0u, g_status.atom_number);
        EXPECT_EQ(kArmMaliResultTerminated, g_status.result_code);

        // Shouldn't do anything.
        MsdArmAtom atom(connection, 0, 1, 5, magma_arm_mali_user_data{7, 8}, 0);
        connection->SendNotificationData(&atom, static_cast<ArmMaliResultCode>(10));
        EXPECT_EQ(kArmMaliResultTerminated, g_status.result_code);

        connection->SetNotificationCallback(nullptr, 0);

        EXPECT_EQ(1u, owner.cancel_atoms_list().size());
        EXPECT_EQ(connection.get(), owner.cancel_atoms_list()[0]);
    }

    void SoftwareAtom()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);

        magma_arm_mali_atom client_atom = {};
        client_atom.flags = kAtomFlagSemaphoreWait;
        std::deque<std::shared_ptr<magma::PlatformSemaphore>> semaphores;
        EXPECT_FALSE(connection->ExecuteAtom(&client_atom, &semaphores));

        std::shared_ptr<magma::PlatformSemaphore> semaphore(magma::PlatformSemaphore::Create());
        semaphores.push_back(semaphore);
        EXPECT_TRUE(connection->ExecuteAtom(&client_atom, &semaphores));

        EXPECT_EQ(1u, owner.atoms_list().size());
        std::shared_ptr<MsdArmAtom> atom = owner.atoms_list()[0];
        std::shared_ptr<MsdArmSoftAtom> soft_atom = MsdArmSoftAtom::cast(atom);
        EXPECT_TRUE(!!soft_atom);
        EXPECT_EQ(kAtomFlagSemaphoreWait, soft_atom->soft_flags());
        EXPECT_EQ(semaphore, soft_atom->platform_semaphore());
    }

    void FlushRegion()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = PAGE_SIZE * 100;

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);

        constexpr uint64_t kGpuOffset[] = {1000, 1100, 1200};

        auto mapping0 = std::make_unique<GpuMapping>(kGpuOffset[0] * PAGE_SIZE, 1, PAGE_SIZE * 5, 0,
                                                     connection.get(), buffer);
        EXPECT_TRUE(connection->AddMapping(std::move(mapping0)));

        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 99));
        EXPECT_EQ(static_cast<uint32_t>(PAGE_SIZE), buffer->flushed_region_start_bytes_);
        EXPECT_EQ(static_cast<uint32_t>(PAGE_SIZE * 6), buffer->flushed_region_end_bytes_);

        auto mapping1 = std::make_unique<GpuMapping>(kGpuOffset[1] * PAGE_SIZE, 1, PAGE_SIZE * 6, 0,
                                                     connection.get(), buffer);
        EXPECT_TRUE(connection->AddMapping(std::move(mapping1)));

        EXPECT_EQ(static_cast<uint32_t>(PAGE_SIZE), buffer->flushed_region_start_bytes_);
        EXPECT_EQ(static_cast<uint32_t>(PAGE_SIZE * 7), buffer->flushed_region_end_bytes_);

        // Outer cache-coherent mappings shouldn't flush pages.
        auto mapping2 = std::make_unique<GpuMapping>(kGpuOffset[2] * PAGE_SIZE, 1, PAGE_SIZE * 99,
                                                     kMagmaArmMaliGpuMapFlagBothShareable,
                                                     connection.get(), buffer);
        EXPECT_TRUE(connection->AddMapping(std::move(mapping2)));
        EXPECT_EQ(static_cast<uint32_t>(PAGE_SIZE), buffer->flushed_region_start_bytes_);
        EXPECT_EQ(static_cast<uint32_t>(PAGE_SIZE * 7), buffer->flushed_region_end_bytes_);
    }

    void FlushUncachedRegion()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = PAGE_SIZE * 100;

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);
        EXPECT_TRUE(buffer->platform_buffer()->SetCachePolicy(MAGMA_CACHE_POLICY_UNCACHED));

        constexpr uint64_t kGpuOffset = 1000;
        auto mapping = std::make_unique<GpuMapping>(kGpuOffset * PAGE_SIZE, 1, PAGE_SIZE * 99, 0,
                                                    connection.get(), buffer);
        EXPECT_TRUE(connection->AddMapping(std::move(mapping)));

        // Mappings of uncached buffers shouldn't flush pages.
        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), 1, 1));
        EXPECT_EQ(0u, buffer->flushed_region_start_bytes_);
        EXPECT_EQ(0u, buffer->flushed_region_end_bytes_);
    }

    void PhysicalToVirtual()
    {
        FakeConnectionOwner owner;
        auto connection = MsdArmConnection::Create(0, &owner);
        EXPECT_TRUE(connection);
        constexpr uint64_t kBufferSize = PAGE_SIZE * 100;

        std::shared_ptr<MsdArmBuffer> buffer(
            MsdArmBuffer::Create(kBufferSize, "test-buffer").release());
        EXPECT_TRUE(buffer);

        constexpr uint64_t kGpuOffset = 1100;
        constexpr uint32_t kMappingOffsetInPages = 1;

        auto mapping = std::make_unique<GpuMapping>(kGpuOffset * PAGE_SIZE, kMappingOffsetInPages,
                                                    PAGE_SIZE * 5, 0, connection.get(), buffer);
        EXPECT_TRUE(connection->AddMapping(std::move(mapping)));
        EXPECT_TRUE(connection->CommitMemoryForBuffer(buffer.get(), kMappingOffsetInPages, 2));

        auto bus_mapping = owner.GetBusMapper()->MapPageRangeBus(buffer->platform_buffer(), 0, 100);
        constexpr uint32_t kPageOffsetIntoBuffer = 2;
        uint64_t physical = bus_mapping->Get()[kPageOffsetIntoBuffer] + 300;
        uint64_t virtual_address;
        EXPECT_TRUE(connection->GetVirtualAddressFromPhysical(physical, &virtual_address));
        EXPECT_EQ((kGpuOffset + kPageOffsetIntoBuffer - kMappingOffsetInPages) * PAGE_SIZE + 300,
                  virtual_address);

        // Don't check uncommitted pages inside mapping.
        physical = bus_mapping->Get()[4] + 300;
        EXPECT_FALSE(connection->GetVirtualAddressFromPhysical(physical, &virtual_address));

        // Don't check pages after mapping.
        physical = bus_mapping->Get()[6] + 300;
        EXPECT_FALSE(connection->GetVirtualAddressFromPhysical(physical, &virtual_address));

        // Don't check pages before mapping.
        physical = bus_mapping->Get()[0] + 300;
        EXPECT_FALSE(connection->GetVirtualAddressFromPhysical(physical, &virtual_address));
    }

    void DeregisterConnection()
    {
        DeregisterConnectionOwner owner;
        {
            auto connection = MsdArmConnection::Create(0, &owner);
            EXPECT_TRUE(connection);
            owner.set_connection(connection);
        }
    }
};

TEST(TestConnection, MapUnmap)
{
    TestConnection test;
    test.MapUnmap();
}

TEST(TestConnection, CommitMemory)
{
    TestConnection test;
    test.CommitMemory();
}

TEST(TestConnection, CommitLargeBuffer)
{
    TestConnection test;
    test.CommitLargeBuffer();
}

TEST(TestConnection, Notification)
{
    TestConnection test;
    test.Notification();
}

TEST(TestConnection, DestructionNotification)
{
    TestConnection test;
    test.DestructionNotification();
}

TEST(TestConnection, SoftwareAtom)
{
    TestConnection test;
    test.SoftwareAtom();
}

TEST(TestConnection, GrowableMemory)
{
    TestConnection test;
    test.GrowableMemory();
}

TEST(TestConnection, FlushRegion)
{
    TestConnection test;
    test.FlushRegion();
}

TEST(TestConnection, FlushUncachedRegion)
{
    TestConnection test;
    test.FlushUncachedRegion();
}

TEST(TestConnection, PhysicalToVirtual)
{
    TestConnection test;
    test.PhysicalToVirtual();
}

TEST(TestConnection, DeregisterConnection)
{
    TestConnection test;
    test.DeregisterConnection();
}
