compute-runtime/shared/test/unit_test/helpers/memory_management_tests.cpp

192 lines
7.3 KiB
C++

/*
* Copyright (C) 2018-2023 Intel Corporation
*
* SPDX-License-Identifier: MIT
*
*/
#include "shared/source/memory_manager/compression_selector.h"
#include "shared/test/common/fixtures/memory_management_fixture.h"
#include "shared/test/common/helpers/debug_manager_state_restore.h"
#include "shared/test/common/helpers/memory_management.h"
#include "shared/test/common/helpers/variable_backup.h"
#include "gtest/gtest.h"
using MemoryManagement::AllocationEvent;
using MemoryManagement::eventsAllocated;
using MemoryManagement::eventsDeallocated;
using MemoryManagement::failingAllocation;
using MemoryManagement::indexAllocation;
using MemoryManagement::indexDeallocation;
using MemoryManagement::numAllocations;
namespace NEO {
extern bool isStatelessCompressionSupportedForUlts;
}
TEST(allocation, GivenFailingAllocationNegativeOneWhenCreatingAllocationThenAllocationIsCreatedSuccesfully) {
ASSERT_EQ(failingAllocation, static_cast<size_t>(-1));
auto ptr = new (std::nothrow) char;
EXPECT_NE(nullptr, ptr);
delete ptr;
}
TEST(allocation, GivenFailingAllocationOneWhenCreatingAllocationsThenOnlyOneAllocationIsCreatedSuccesfully) {
MemoryManagement::detailedAllocationLoggingActive = true;
ASSERT_EQ(static_cast<size_t>(-1), failingAllocation);
auto previousAllocations = numAllocations.load();
MemoryManagement::indexAllocation = 0;
failingAllocation = 1;
auto ptr1 = new (std::nothrow) char;
auto ptr2 = new (std::nothrow) char;
delete ptr1;
delete ptr2;
auto currentAllocations = numAllocations.load();
failingAllocation = -1;
EXPECT_NE(nullptr, ptr1);
EXPECT_EQ(nullptr, ptr2); // NOLINT(clang-analyzer-cplusplus.NewDelete)
EXPECT_EQ(previousAllocations, currentAllocations);
MemoryManagement::detailedAllocationLoggingActive = false;
}
TEST(CompressionSelector, WhenAllowStatelessCompressionIsCalledThenReturnCorrectValue) {
DebugManagerStateRestore restore;
VariableBackup<bool> backup(&NEO::isStatelessCompressionSupportedForUlts);
NEO::isStatelessCompressionSupportedForUlts = false;
EXPECT_FALSE(CompressionSelector::allowStatelessCompression());
NEO::isStatelessCompressionSupportedForUlts = true;
for (auto enable : {-1, 0, 1}) {
debugManager.flags.EnableStatelessCompression.set(enable);
if (enable > 0) {
EXPECT_TRUE(CompressionSelector::allowStatelessCompression());
} else {
EXPECT_FALSE(CompressionSelector::allowStatelessCompression());
}
}
}
struct MemoryManagementTest : public MemoryManagementFixture,
public ::testing::Test {
void SetUp() override {
MemoryManagementFixture::setUp();
}
void TearDown() override {
MemoryManagementFixture::tearDown();
}
};
TEST_F(MemoryManagementTest, GivenFailingAllocationOneWhenCreatingAllocationsThenOnlyOneAllocationIsCreatedSuccesfully) {
setFailingAllocation(1);
auto ptr1 = new (std::nothrow) char;
auto ptr2 = new (std::nothrow) char;
delete ptr1;
delete ptr2;
clearFailingAllocation();
EXPECT_NE(nullptr, ptr1);
EXPECT_EQ(nullptr, ptr2); // NOLINT(clang-analyzer-cplusplus.NewDelete)
}
TEST_F(MemoryManagementTest, GivenNoFailingAllocationWhenCreatingAllocationThenMemoryIsNotLeaked) {
auto indexAllocationTop = indexAllocation.load();
auto indexDellocationTop = indexDeallocation.load();
EXPECT_EQ(static_cast<size_t>(-1), MemoryManagement::enumerateLeak(indexAllocationTop, indexDellocationTop, false, false));
}
TEST_F(MemoryManagementTest, GivenOneFailingAllocationWhenCreatingAllocationThenMemoryIsLeaked) {
size_t sizeBuffer = 10;
auto ptr = new (std::nothrow) char[sizeBuffer];
auto indexAllocationTop = indexAllocation.load();
auto indexDeallocationTop = indexDeallocation.load();
auto leakIndex = MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false);
ASSERT_NE(static_cast<size_t>(-1), leakIndex); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
EXPECT_EQ(ptr, eventsAllocated[leakIndex].address);
EXPECT_EQ(sizeBuffer, eventsAllocated[leakIndex].size);
// Not expecting any more failures
EXPECT_EQ(static_cast<size_t>(-1), MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false));
delete[] ptr;
}
TEST_F(MemoryManagementTest, GivenFourEventsWhenCreatingAllocationThenMemoryIsLeakedOnce) {
size_t sizeBuffer = 10;
delete new (std::nothrow) char;
auto ptr = new (std::nothrow) char[sizeBuffer];
delete new (std::nothrow) char;
auto indexAllocationTop = indexAllocation.load();
auto indexDeallocationTop = indexDeallocation.load();
auto leakIndex = MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false);
ASSERT_NE(static_cast<size_t>(-1), leakIndex); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
EXPECT_EQ(ptr, eventsAllocated[leakIndex].address);
EXPECT_EQ(sizeBuffer, eventsAllocated[leakIndex].size);
// Not expecting any more failures
EXPECT_EQ(static_cast<size_t>(-1), MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false));
delete[] ptr;
}
TEST_F(MemoryManagementTest, GivenTwoFailingAllocationsWhenCreatingAllocationThenMemoryIsLeaked) {
size_t sizeBuffer = 10;
auto ptr1 = new (std::nothrow) char[sizeBuffer];
auto ptr2 = new (std::nothrow) char[sizeBuffer];
auto indexAllocationTop = indexAllocation.load();
auto indexDeallocationTop = indexDeallocation.load();
auto leakIndex1 = MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false);
auto leakIndex2 = MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false);
ASSERT_NE(static_cast<size_t>(-1), leakIndex1); // NOLINT(clang-analyzer-cplusplus.NewDeleteLeaks)
EXPECT_EQ(ptr1, eventsAllocated[leakIndex1].address);
EXPECT_EQ(sizeBuffer, eventsAllocated[leakIndex1].size);
ASSERT_NE(static_cast<size_t>(-1), leakIndex2);
EXPECT_EQ(ptr2, eventsAllocated[leakIndex2].address);
EXPECT_EQ(sizeBuffer, eventsAllocated[leakIndex2].size);
// Not expecting any more failures
EXPECT_EQ(static_cast<size_t>(-1), MemoryManagement::enumerateLeak(indexAllocationTop, indexDeallocationTop, false, false));
delete[] ptr1;
delete[] ptr2;
}
TEST_F(MemoryManagementTest, WhenDeletingNullPtrThenLeakIsNotReported) {
char *ptr = nullptr;
delete ptr;
}
TEST_F(MemoryManagementTest, WhenPointerIsDeletedThenAllocationShouldbeVisible) {
size_t sizeBuffer = 10;
auto index = MemoryManagement::indexAllocation.load();
auto ptr = new (std::nothrow) char[sizeBuffer];
EXPECT_EQ(ptr, eventsAllocated[index].address);
EXPECT_EQ(sizeBuffer, eventsAllocated[index].size);
index = MemoryManagement::indexDeallocation;
uintptr_t ptrCopy = reinterpret_cast<uintptr_t>(ptr);
delete[] ptr;
EXPECT_EQ(ptrCopy, reinterpret_cast<uintptr_t>(eventsDeallocated[index].address));
}
#if ENABLE_ME_FOR_LEAK_TESTING
TEST_F(MemoryManagementTest, GivenEnableForLeakTestingThenDetectLeak) {
// Useful reference : MemoryManagement::onAllocationEvent
MemoryManagement::breakOnAllocationEvent = 1;
MemoryManagement::breakOnDeallocationEvent = 0;
delete new char;
new char;
MemoryManagement::breakOnAllocationEvent = -1;
MemoryManagement::breakOnDeallocationEvent = -1;
}
#endif