• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://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,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <thread>
17 #include <sstream>
18 #include <gtest/gtest.h>
19 #include "mem/alloc_tracker.h"
20 
21 namespace panda {
22 
23 struct Header {
24     uint32_t num_items = 0;
25     uint32_t num_stacktraces = 0;
26 };
27 
28 struct AllocInfo {
29     uint32_t tag = 0;
30     uint32_t id = 0;
31     uint32_t size = 0;
32     uint32_t space = 0;
33     uint32_t stacktrace_id = 0;
34 };
35 
36 struct FreeInfo {
37     uint32_t tag = 0;
38     uint32_t alloc_id = 0;
39 };
40 
SkipString(std::istream & in)41 static void SkipString(std::istream &in)
42 {
43     uint32_t len = 0;
44     in.read(reinterpret_cast<char *>(&len), sizeof(len));
45     if (!in) {
46         return;
47     }
48     in.seekg(len, std::ios_base::cur);
49 }
50 
TEST(DetailAllocTrackerTest,NoAllocs)51 TEST(DetailAllocTrackerTest, NoAllocs)
52 {
53     DetailAllocTracker tracker;
54     std::stringstream out;
55     tracker.Dump(out);
56     out.seekg(0);
57 
58     Header hdr;
59     out.read(reinterpret_cast<char *>(&hdr), sizeof(hdr));
60     ASSERT_FALSE(out.eof());
61     ASSERT_EQ(0, hdr.num_items);
62     ASSERT_EQ(0, hdr.num_stacktraces);
63 }
64 
TEST(DetailAllocTrackerTest,OneAlloc)65 TEST(DetailAllocTrackerTest, OneAlloc)
66 {
67     DetailAllocTracker tracker;
68     std::stringstream out;
69     tracker.TrackAlloc(reinterpret_cast<void *>(0x15), 20, SpaceType::SPACE_TYPE_INTERNAL);
70     tracker.Dump(out);
71     out.seekg(0);
72 
73     Header hdr;
74     out.read(reinterpret_cast<char *>(&hdr), sizeof(hdr));
75     ASSERT_FALSE(out.eof());
76     ASSERT_EQ(1, hdr.num_items);
77     ASSERT_EQ(1, hdr.num_stacktraces);
78 
79     // skip stacktrace
80     SkipString(out);
81     ASSERT_FALSE(out.eof());
82     AllocInfo info;
83     out.read(reinterpret_cast<char *>(&info), sizeof(info));
84     ASSERT_FALSE(out.eof());
85     ASSERT_EQ(DetailAllocTracker::ALLOC_TAG, info.tag);
86     ASSERT_EQ(0, info.id);
87     ASSERT_EQ(20, info.size);
88     ASSERT_EQ(static_cast<uint32_t>(SpaceType::SPACE_TYPE_INTERNAL), info.space);
89     ASSERT_EQ(0, info.stacktrace_id);
90 }
91 
TEST(DetailAllocTrackerTest,AllocAndFree)92 TEST(DetailAllocTrackerTest, AllocAndFree)
93 {
94     DetailAllocTracker tracker;
95     std::stringstream out;
96     tracker.TrackAlloc(reinterpret_cast<void *>(0x15), 20, SpaceType::SPACE_TYPE_INTERNAL);
97     tracker.TrackFree(reinterpret_cast<void *>(0x15));
98     tracker.Dump(out);
99     out.seekg(0);
100 
101     Header hdr;
102     out.read(reinterpret_cast<char *>(&hdr), sizeof(hdr));
103     ASSERT_FALSE(out.eof());
104     ASSERT_EQ(2, hdr.num_items);
105     ASSERT_EQ(1, hdr.num_stacktraces);
106 
107     // skip stacktrace
108     SkipString(out);
109     ASSERT_FALSE(out.eof());
110     AllocInfo alloc;
111     FreeInfo free;
112     out.read(reinterpret_cast<char *>(&alloc), sizeof(alloc));
113     out.read(reinterpret_cast<char *>(&free), sizeof(free));
114     ASSERT_FALSE(out.eof());
115     ASSERT_EQ(DetailAllocTracker::ALLOC_TAG, alloc.tag);
116     ASSERT_EQ(0, alloc.id);
117     ASSERT_EQ(20, alloc.size);
118     ASSERT_EQ(static_cast<uint32_t>(SpaceType::SPACE_TYPE_INTERNAL), alloc.space);
119     ASSERT_EQ(0, alloc.stacktrace_id);
120     ASSERT_EQ(DetailAllocTracker::FREE_TAG, free.tag);
121     ASSERT_EQ(0, free.alloc_id);
122 }
123 
TEST(DetailAllocTrackerTest,MultithreadedAlloc)124 TEST(DetailAllocTrackerTest, MultithreadedAlloc)
125 {
126     static constexpr size_t NUM_THREADS = 10;
127     static constexpr size_t NUM_ITERS = 100;
128 
129     DetailAllocTracker tracker;
130     std::vector<std::thread> threads;
131     for (size_t i = 0; i < NUM_THREADS; ++i) {
132         threads.emplace_back(
133             [&tracker](size_t thread_num) {
134                 for (size_t iter = 0; iter < NUM_ITERS; ++iter) {
135                     auto addr = reinterpret_cast<void *>(thread_num * NUM_THREADS + iter + 1);
136                     tracker.TrackAlloc(addr, 10, SpaceType::SPACE_TYPE_INTERNAL);
137                 }
138             },
139             i);
140     }
141 
142     for (auto &thread : threads) {
143         thread.join();
144     }
145 
146     std::stringstream out;
147     tracker.Dump(out);
148     out.seekg(0);
149 
150     Header hdr;
151     out.read(reinterpret_cast<char *>(&hdr), sizeof(hdr));
152     ASSERT_FALSE(out.eof());
153     ASSERT_EQ(NUM_THREADS * NUM_ITERS, hdr.num_items);
154     ASSERT_EQ(1, hdr.num_stacktraces);
155 }
156 
157 }  // namespace panda
158