From 320ef65362608ee1148c299d8d5d7618af34e470 Mon Sep 17 00:00:00 2001 From: Boyuan Yang Date: Sun, 7 Nov 2021 08:50:18 -0500 Subject: New upstream version 0.17.0 --- src/utils/memory_test.cc | 184 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 184 insertions(+) create mode 100644 src/utils/memory_test.cc (limited to 'src/utils/memory_test.cc') diff --git a/src/utils/memory_test.cc b/src/utils/memory_test.cc new file mode 100644 index 0000000..42f6a15 --- /dev/null +++ b/src/utils/memory_test.cc @@ -0,0 +1,184 @@ +// Copyright 2021 The libgav1 Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include "src/utils/memory.h" + +#include +#include +#include +#include + +#include "absl/base/config.h" +#include "gtest/gtest.h" + +#ifdef ABSL_HAVE_EXCEPTIONS +#include +#endif + +namespace libgav1 { +namespace { + +constexpr size_t kMaxAllocableSize = 0x40000000; + +struct Small : public Allocable { + uint8_t x; +}; + +struct Huge : public Allocable { + uint8_t x[kMaxAllocableSize + 1]; +}; + +struct SmallMaxAligned : public MaxAlignedAllocable { + alignas(kMaxAlignment) uint8_t x; +}; + +struct HugeMaxAligned : public MaxAlignedAllocable { + alignas(kMaxAlignment) uint8_t x[kMaxAllocableSize + 1]; +}; + +#ifdef ABSL_HAVE_EXCEPTIONS +struct ThrowingConstructor : public Allocable { + ThrowingConstructor() { throw std::exception(); } + + uint8_t x; +}; + +struct MaxAlignedThrowingConstructor : public MaxAlignedAllocable { + MaxAlignedThrowingConstructor() { throw std::exception(); } + + uint8_t x; +}; +#endif + +TEST(MemoryTest, TestAlignedAllocFree) { + for (size_t alignment = 1; alignment <= 1 << 20; alignment <<= 1) { + void* p = AlignedAlloc(alignment, 1); + // Note this additional check is to avoid an incorrect static-analysis + // warning for leaked memory with a plain ASSERT_NE(). + if (p == nullptr) { + FAIL() << "AlignedAlloc(" << alignment << ", 1)"; + } + const auto p_value = reinterpret_cast(p); + EXPECT_EQ(p_value % alignment, 0) + << "AlignedAlloc(" << alignment << ", 1) = " << p; + AlignedFree(p); + } +} + +TEST(MemoryTest, TestAlignedUniquePtrAlloc) { + for (size_t alignment = 1; alignment <= 1 << 20; alignment <<= 1) { + auto p = MakeAlignedUniquePtr(alignment, 1); + ASSERT_NE(p, nullptr) << "MakeAlignedUniquePtr(" << alignment << ", 1)"; + const auto p_value = reinterpret_cast(p.get()); + EXPECT_EQ(p_value % alignment, 0) + << "MakeAlignedUniquePtr(" << alignment << ", 1) = " << p.get(); + } +} + +TEST(MemoryTest, TestAllocable) { + // Allocable::operator new (std::nothrow) is called. + std::unique_ptr small(new (std::nothrow) Small); + EXPECT_NE(small, nullptr); + // Allocable::operator delete is called. + small = nullptr; + + // Allocable::operator new[] (std::nothrow) is called. + std::unique_ptr small_array_of_smalls(new (std::nothrow) Small[10]); + EXPECT_NE(small_array_of_smalls, nullptr); + // Allocable::operator delete[] is called. + small_array_of_smalls = nullptr; + + // Allocable::operator new (std::nothrow) is called. + std::unique_ptr huge(new (std::nothrow) Huge); + EXPECT_EQ(huge, nullptr); + + // Allocable::operator new[] (std::nothrow) is called. + std::unique_ptr huge_array_of_smalls( + new (std::nothrow) Small[kMaxAllocableSize / sizeof(Small) + 1]); + EXPECT_EQ(huge_array_of_smalls, nullptr); + +#ifdef ABSL_HAVE_EXCEPTIONS + try { + // Allocable::operator new (std::nothrow) is called. + // The constructor throws an exception. + // Allocable::operator delete (std::nothrow) is called. + ThrowingConstructor* always = new (std::nothrow) ThrowingConstructor; + static_cast(always); + } catch (...) { + } + + try { + // Allocable::operator new[] (std::nothrow) is called. + // The constructor throws an exception. + // Allocable::operator delete[] (std::nothrow) is called. + ThrowingConstructor* always = new (std::nothrow) ThrowingConstructor[2]; + static_cast(always); + } catch (...) { + } +#endif // ABSL_HAVE_EXCEPTIONS +} + +TEST(MemoryTest, TestMaxAlignedAllocable) { + // MaxAlignedAllocable::operator new (std::nothrow) is called. + std::unique_ptr small(new (std::nothrow) SmallMaxAligned); + EXPECT_NE(small, nullptr); + // Note this check doesn't guarantee conformance as a suitably aligned + // address may be returned from any allocator. + EXPECT_EQ(reinterpret_cast(small.get()) & (kMaxAlignment - 1), 0); + // MaxAlignedAllocable::operator delete is called. + small = nullptr; + + // MaxAlignedAllocable::operator new[] (std::nothrow) is called. + std::unique_ptr small_array_of_smalls( + new (std::nothrow) SmallMaxAligned[10]); + EXPECT_NE(small_array_of_smalls, nullptr); + EXPECT_EQ(reinterpret_cast(small_array_of_smalls.get()) & + (kMaxAlignment - 1), + 0); + // MaxAlignedAllocable::operator delete[] is called. + small_array_of_smalls = nullptr; + + // MaxAlignedAllocable::operator new (std::nothrow) is called. + std::unique_ptr huge(new (std::nothrow) HugeMaxAligned); + EXPECT_EQ(huge, nullptr); + + // MaxAlignedAllocable::operator new[] (std::nothrow) is called. + std::unique_ptr huge_array_of_smalls( + new (std::nothrow) + SmallMaxAligned[kMaxAllocableSize / sizeof(SmallMaxAligned) + 1]); + EXPECT_EQ(huge_array_of_smalls, nullptr); + +#ifdef ABSL_HAVE_EXCEPTIONS + try { + // MaxAlignedAllocable::operator new (std::nothrow) is called. + // The constructor throws an exception. + // MaxAlignedAllocable::operator delete (std::nothrow) is called. + auto* always = new (std::nothrow) MaxAlignedThrowingConstructor; + static_cast(always); + } catch (...) { + } + + try { + // MaxAlignedAllocable::operator new[] (std::nothrow) is called. + // The constructor throws an exception. + // MaxAlignedAllocable::operator delete[] (std::nothrow) is called. + auto* always = new (std::nothrow) MaxAlignedThrowingConstructor[2]; + static_cast(always); + } catch (...) { + } +#endif // ABSL_HAVE_EXCEPTIONS +} + +} // namespace +} // namespace libgav1 -- cgit v1.2.3