1 // Copyright 2024 The Pigweed Authors
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License"); you may not
4 // use this file except in compliance with the License. You may obtain a copy of
5 // the License at
6 //
7 // https://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11 // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12 // License for the specific language governing permissions and limitations under
13 // the License.
14
15 #include "pw_malloc/malloc.h"
16
17 #include <cstdint>
18
19 #include "pw_unit_test/framework.h"
20
21 namespace {
22
23 class MallocTest : public ::testing::Test {
24 protected:
SetUp()25 void SetUp() override { pw::malloc::InitSystemAllocator(heap_); }
26
27 private:
28 std::array<std::byte, 1024> heap_;
29 };
30
TEST_F(MallocTest,MallocFree)31 TEST_F(MallocTest, MallocFree) {
32 constexpr size_t kSize = 256;
33 auto& system_metrics = pw::malloc::GetSystemMetrics();
34 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
35
36 void* ptr = malloc(kSize);
37 ASSERT_NE(ptr, nullptr);
38 EXPECT_EQ(system_metrics.requested_bytes.value(), kSize);
39
40 free(ptr);
41 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
42 }
43
TEST_F(MallocTest,NewDelete)44 TEST_F(MallocTest, NewDelete) {
45 constexpr size_t kSize = 256;
46 auto& system_metrics = pw::malloc::GetSystemMetrics();
47 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
48
49 auto* ptr = new std::array<std::byte, kSize>();
50 ASSERT_NE(ptr, nullptr);
51 EXPECT_GE(system_metrics.allocated_bytes.value(), kSize);
52
53 delete (ptr);
54 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
55 }
56
TEST_F(MallocTest,CallocFree)57 TEST_F(MallocTest, CallocFree) {
58 constexpr size_t kNum = 4;
59 constexpr size_t kSize = 64;
60 auto& system_metrics = pw::malloc::GetSystemMetrics();
61 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
62
63 void* ptr = calloc(kNum, kSize);
64 ASSERT_NE(ptr, nullptr);
65 EXPECT_EQ(system_metrics.requested_bytes.value(), kNum * kSize);
66
67 free(ptr);
68 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
69 }
70
TEST_F(MallocTest,ReallocFree)71 TEST_F(MallocTest, ReallocFree) {
72 constexpr size_t kSize = 256;
73 auto& system_metrics = pw::malloc::GetSystemMetrics();
74 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
75
76 void* ptr = realloc(nullptr, kSize);
77 ASSERT_NE(ptr, nullptr);
78 EXPECT_EQ(system_metrics.requested_bytes.value(), kSize);
79
80 free(ptr);
81 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
82 }
83
TEST_F(MallocTest,MallocReallocFree)84 TEST_F(MallocTest, MallocReallocFree) {
85 constexpr size_t kSize1 = 256;
86 constexpr size_t kSize2 = 512;
87 auto& system_metrics = pw::malloc::GetSystemMetrics();
88 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
89
90 void* ptr = malloc(kSize1);
91 ASSERT_NE(ptr, nullptr);
92 EXPECT_EQ(system_metrics.requested_bytes.value(), kSize1);
93 std::memset(ptr, 1, kSize1);
94
95 void* new_ptr = realloc(ptr, kSize2);
96 ASSERT_NE(ptr, nullptr);
97 EXPECT_EQ(system_metrics.requested_bytes.value(), kSize2);
98
99 // Using `new_ptr` prevents the call to `realloc from being optimized away.
100 auto* bytes = std::launder(reinterpret_cast<uint8_t*>(new_ptr));
101 for (size_t i = 0; i < kSize1; ++i) {
102 EXPECT_EQ(bytes[i], 1U);
103 }
104
105 free(new_ptr);
106 EXPECT_EQ(system_metrics.allocated_bytes.value(), 0U);
107 }
108
109 } // namespace
110