blob: bd6ab4693e6bfb52ba94557306d341fd240d9583 [file] [log] [blame]
// Copyright 2022 The Chromium 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 "ipcz/driver_memory.h"
#include "ipcz/driver_memory_mapping.h"
#include "test/mock_driver.h"
#include "test/test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "util/ref_counted.h"
namespace ipcz {
namespace {
using testing::_;
using testing::Return;
class DriverMemoryTest : public test::Test {
public:
DriverMemoryTest() = default;
~DriverMemoryTest() override = default;
test::MockDriver& driver() { return driver_; }
private:
::testing::StrictMock<test::MockDriver> driver_;
};
TEST_F(DriverMemoryTest, Invalid) {
DriverMemory memory;
EXPECT_FALSE(memory.is_valid());
}
TEST_F(DriverMemoryTest, AcquireFromObject) {
constexpr IpczDriverHandle kHandle = 1234;
constexpr size_t kSize = 64;
DriverObject object(test::kMockDriver, kHandle);
// Constructing a new DriverMemory over a generic DriverObject must query the
// underlying object for its size.
EXPECT_CALL(driver(), GetSharedMemoryInfo(kHandle, _, _, _))
.WillOnce([](IpczDriverHandle handle, uint32_t, const void*,
IpczSharedMemoryInfo* info) {
info->region_num_bytes = kSize;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
// DriverMemory must reflect the size returned by the driver.
DriverMemory memory(std::move(object));
EXPECT_EQ(kSize, memory.size());
EXPECT_CALL(driver(), Close(kHandle, _, _));
}
TEST_F(DriverMemoryTest, Allocate) {
constexpr IpczDriverHandle kHandle = 54321;
constexpr size_t kSize = 256;
// Constructing a new DriverMemory with a size should allocate a new shared
// memory region through the driver.
EXPECT_CALL(driver(), AllocateSharedMemory(kSize, _, _, _))
.WillOnce([&](size_t num_bytes, uint32_t, const void*,
IpczDriverHandle* handle) {
*handle = kHandle;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
DriverMemory memory(test::kMockDriver, kSize);
EXPECT_EQ(kHandle, memory.driver_object().handle());
EXPECT_EQ(kSize, memory.size());
EXPECT_CALL(driver(), Close(kHandle, _, _));
}
TEST_F(DriverMemoryTest, Clone) {
constexpr IpczDriverHandle kHandle = 54321;
constexpr IpczDriverHandle kDupe = 1234;
constexpr size_t kSize = 256;
EXPECT_CALL(driver(), AllocateSharedMemory(kSize, _, _, _))
.WillOnce([&](size_t num_bytes, uint32_t, const void*,
IpczDriverHandle* handle) {
*handle = kHandle;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
DriverMemory memory(test::kMockDriver, kSize);
EXPECT_CALL(driver(), DuplicateSharedMemory(kHandle, _, _, _))
.WillOnce([&](IpczDriverHandle memory, uint32_t, const void*,
IpczDriverHandle* new_handle) {
*new_handle = kDupe;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
EXPECT_CALL(driver(), GetSharedMemoryInfo(kDupe, _, _, _))
.WillOnce([](IpczDriverHandle handle, uint32_t, const void*,
IpczSharedMemoryInfo* info) {
info->region_num_bytes = kSize;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
DriverMemory clone = memory.Clone();
EXPECT_TRUE(clone.is_valid());
EXPECT_EQ(kDupe, clone.driver_object().handle());
EXPECT_EQ(kSize, clone.size());
EXPECT_CALL(driver(), Close(kHandle, _, _));
EXPECT_CALL(driver(), Close(kDupe, _, _));
}
TEST_F(DriverMemoryTest, Map) {
constexpr IpczDriverHandle kHandle = 424242;
constexpr IpczDriverHandle kMapping = 777;
constexpr size_t kSize = 64;
uint8_t data[64] = {0};
void* kMappingAddress = &data[0];
EXPECT_CALL(driver(), AllocateSharedMemory(kSize, _, _, _))
.WillOnce([&](size_t num_bytes, uint32_t, const void*,
IpczDriverHandle* handle) {
*handle = kHandle;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
DriverMemory memory(test::kMockDriver, kSize);
EXPECT_CALL(driver(), MapSharedMemory(kHandle, _, _, _, _))
.WillOnce([&](IpczDriverHandle memory, uint32_t, const void*, void** addr,
IpczDriverHandle* mapping) {
*addr = kMappingAddress;
*mapping = kMapping;
return IPCZ_RESULT_OK;
})
.RetiresOnSaturation();
DriverMemoryMapping mapping = memory.Map();
EXPECT_TRUE(mapping.is_valid());
EXPECT_EQ(kMappingAddress, mapping.address());
EXPECT_EQ(&data[0], mapping.bytes().data());
EXPECT_EQ(kSize, mapping.bytes().size());
EXPECT_CALL(driver(), Close(kMapping, _, _));
EXPECT_CALL(driver(), Close(kHandle, _, _));
}
} // namespace
} // namespace ipcz