1 : // Copyright 2013 Google Inc. All Rights Reserved.
2 : //
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 : #include "syzygy/agent/profiler/symbol_map.h"
16 :
17 : #include "gmock/gmock.h"
18 : #include "gtest/gtest.h"
19 :
20 : namespace agent {
21 : namespace profiler {
22 :
23 : namespace {
24 :
25 : class TestingSymbolMap : public SymbolMap {
26 : public:
27 : // Expose the address space for testing.
28 : using SymbolMap::addr_space_;
29 : typedef SymbolMap::SymbolAddressSpace SymbolAddressSpace;
30 : };
31 :
32 E : const uint8* ToPtr(intptr_t number) {
33 E : return reinterpret_cast<const uint8*>(number);
34 E : }
35 :
36 : class SymbolMapTest : public testing::Test {
37 : protected:
38 : TestingSymbolMap symbol_map_;
39 : };
40 :
41 : } // namespace
42 :
43 E : TEST_F(SymbolMapTest, AddSymbol) {
44 : // Insert a symbol.
45 E : const void* kStart = ToPtr(0x1011);
46 E : symbol_map_.AddSymbol(kStart, 0x22, "foo");
47 :
48 : // Reach into the privates of the symbol map and test it's as we expect.
49 E : ASSERT_EQ(1, symbol_map_.addr_space_.size());
50 : TestingSymbolMap::SymbolAddressSpace::iterator it =
51 E : symbol_map_.addr_space_.begin();
52 E : ASSERT_TRUE(it != symbol_map_.addr_space_.end());
53 :
54 E : EXPECT_EQ(it->first.start(), kStart);
55 E : EXPECT_EQ(it->first.size(), 0x22);
56 :
57 : // Test that the new symbol is correctly initialized.
58 E : scoped_refptr<SymbolMap::Symbol> symbol = it->second;
59 E : ASSERT_TRUE(symbol != NULL);
60 E : EXPECT_EQ("foo", symbol->name());
61 E : EXPECT_FALSE(symbol->invalid());
62 E : EXPECT_EQ(0, symbol->id());
63 E : EXPECT_EQ(0, symbol->move_count());
64 E : EXPECT_EQ(kStart, symbol->address());
65 E : }
66 :
67 E : TEST_F(SymbolMapTest, EnsureHasId) {
68 E : const uint8* const kStart = ToPtr(0x1023);
69 :
70 : // Insert a symbol.
71 E : symbol_map_.AddSymbol(kStart, 0x22, "foo");
72 :
73 E : scoped_refptr<SymbolMap::Symbol> symbol = symbol_map_.FindSymbol(kStart);
74 :
75 : // The symbol should not have an ID yet.
76 E : EXPECT_EQ(0, symbol->id());
77 :
78 : // Assign it one.
79 E : EXPECT_TRUE(symbol->EnsureHasId());
80 E : uint32 id = symbol->id();
81 E : EXPECT_NE(0U, id);
82 E : EXPECT_EQ(kStart, symbol->address());
83 :
84 : // We should only get a true return once from EnsureHasId.
85 E : EXPECT_FALSE(symbol->EnsureHasId());
86 : // And the symbol's ID should not change after initial assignment.
87 E : EXPECT_EQ(id, symbol->id());
88 E : }
89 :
90 E : TEST_F(SymbolMapTest, AddMoveSymbol) {
91 : // Insert & move a symbol.
92 E : const void* kSrcAddr = ToPtr(0x1011);
93 E : const void* kDstAddr = ToPtr(0x2000);
94 E : symbol_map_.AddSymbol(kSrcAddr, 0x22, "foo");
95 E : symbol_map_.MoveSymbol(kSrcAddr, kDstAddr);
96 :
97 : // Reach into the privates of the symbol map and test it's as we expect.
98 E : ASSERT_EQ(1, symbol_map_.addr_space_.size());
99 : TestingSymbolMap::SymbolAddressSpace::iterator it =
100 E : symbol_map_.addr_space_.begin();
101 E : ASSERT_TRUE(it != symbol_map_.addr_space_.end());
102 :
103 E : EXPECT_EQ(it->first.start(), kDstAddr);
104 E : EXPECT_EQ(it->first.size(), 0x22);
105 :
106 : // Test that the new symbol is correctly initialized.
107 E : scoped_refptr<SymbolMap::Symbol> symbol = it->second;
108 E : ASSERT_TRUE(symbol != NULL);
109 E : EXPECT_EQ("foo", symbol->name());
110 E : EXPECT_FALSE(symbol->invalid());
111 E : EXPECT_EQ(0, symbol->id());
112 E : EXPECT_EQ(kDstAddr, symbol->address());
113 :
114 : // It should have accrued one move.
115 E : EXPECT_EQ(1, symbol->move_count());
116 E : }
117 :
118 E : TEST_F(SymbolMapTest, FindSymbol) {
119 E : const uint8* const kStart = ToPtr(0x1023);
120 E : ASSERT_TRUE(symbol_map_.FindSymbol(kStart) == NULL);
121 :
122 E : symbol_map_.AddSymbol(kStart, 0x22, "foo");
123 :
124 E : scoped_refptr<SymbolMap::Symbol> symbol = symbol_map_.FindSymbol(kStart);
125 E : ASSERT_TRUE(symbol != NULL);
126 E : ASSERT_EQ(symbol, symbol_map_.FindSymbol(kStart + 1));
127 E : ASSERT_EQ(symbol, symbol_map_.FindSymbol(kStart + 0x21));
128 :
129 E : ASSERT_TRUE(symbol_map_.FindSymbol(kStart + 0x22) == NULL);
130 E : }
131 :
132 E : TEST_F(SymbolMapTest, SymbolLifeCycle) {
133 : // Insert a symbol.
134 E : symbol_map_.AddSymbol(ToPtr(0x1011), 0x22, "foo");
135 :
136 : // Find the symbol through the public symbol map interface.
137 : scoped_refptr<SymbolMap::Symbol> symbol =
138 E : symbol_map_.FindSymbol(ToPtr(0x1026));
139 :
140 E : ASSERT_TRUE(symbol != NULL);
141 E : EXPECT_EQ("foo", symbol->name());
142 E : EXPECT_FALSE(symbol->invalid());
143 :
144 E : EXPECT_EQ(0, symbol->id());
145 E : EXPECT_EQ(0, symbol->move_count());
146 E : EXPECT_EQ(ToPtr(0x1011), symbol->address());
147 :
148 : // Assign an ID to the symbol.
149 E : EXPECT_TRUE(symbol->EnsureHasId());
150 E : uint32 id = symbol->id();
151 E : EXPECT_NE(0U, id);
152 :
153 : // We should only return true on first assigning an id to the symbol.
154 E : EXPECT_FALSE(symbol->EnsureHasId());
155 E : EXPECT_EQ(id, symbol->id());
156 :
157 : // Move "foo".
158 E : symbol_map_.MoveSymbol(ToPtr(0x1011), ToPtr(0x2000));
159 E : EXPECT_EQ(1, symbol->move_count());
160 E : EXPECT_EQ(ToPtr(0x2000), symbol->address());
161 :
162 : // Nothing should be at the original location.
163 E : EXPECT_TRUE(symbol_map_.FindSymbol(ToPtr(0x1026)) == NULL);
164 : // And we should find the same symbol at the new one.
165 E : EXPECT_EQ(symbol, symbol_map_.FindSymbol(ToPtr(0x2014)));
166 E : EXPECT_FALSE(symbol->invalid());
167 E : EXPECT_EQ(id, symbol->id());
168 :
169 : // Add a new symbol, overlapping "foo", this should invalidate the symbol.
170 E : symbol_map_.AddSymbol(ToPtr(0x2010), 0x20, "overlapping");
171 E : EXPECT_TRUE(symbol->invalid());
172 E : EXPECT_EQ(id, symbol->id());
173 : // Note that invalidating a symbol updates the move count.
174 E : EXPECT_EQ(2, symbol->move_count());
175 E : EXPECT_EQ(ToPtr(NULL), symbol->address());
176 E : }
177 :
178 : } // namespace profiler
179 : } // namespace agent
|