1 //===- NamePoolTest.cpp ---------------------------------------------------===//
2 //
3 //                     The MCLinker Project
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 #include "NamePoolTest.h"
10 #include "mcld/LD/NamePool.h"
11 #include "mcld/LD/Resolver.h"
12 #include "mcld/LD/StaticResolver.h"
13 #include "mcld/LD/ResolveInfo.h"
14 #include "mcld/LD/LDSymbol.h"
15 #include <llvm/ADT/StringRef.h>
16 #include <string>
17 #include <cstdio>
18 
19 using namespace mcld;
20 using namespace mcldtest;
21 
22 // Constructor can do set-up work for all test here.
NamePoolTest()23 NamePoolTest::NamePoolTest() {
24   // create testee. modify it if need
25   StaticResolver resolver;
26   m_pTestee = new NamePool(resolver, 10);
27 }
28 
29 // Destructor can do clean-up work that doesn't throw exceptions here.
~NamePoolTest()30 NamePoolTest::~NamePoolTest() {
31   delete m_pTestee;
32 }
33 
34 // SetUp() will be called immediately before each test.
SetUp()35 void NamePoolTest::SetUp() {
36 }
37 
38 // TearDown() will be called immediately after each test.
TearDown()39 void NamePoolTest::TearDown() {
40 }
41 
42 //==========================================================================//
43 // Testcases
44 //
45 
TEST_F(NamePoolTest,insertString)46 TEST_F(NamePoolTest, insertString) {
47   const char* s1 = "Hello MCLinker";
48   llvm::StringRef result1 = m_pTestee->insertString(s1);
49   EXPECT_NE(s1, result1.data());
50   EXPECT_STREQ(s1, result1.data());
51 }
52 
TEST_F(NamePoolTest,insertSameString)53 TEST_F(NamePoolTest, insertSameString) {
54   const char* s1 = "Hello MCLinker";
55   std::string s2(s1);
56   llvm::StringRef result1 = m_pTestee->insertString(s1);
57   llvm::StringRef result2 = m_pTestee->insertString(s2.c_str());
58   EXPECT_STREQ(s1, result1.data());
59   EXPECT_STREQ(s2.c_str(), result2.data());
60   EXPECT_EQ(result1.data(), result2.data());
61 }
62 
TEST_F(NamePoolTest,insert_local_defined_Symbol)63 TEST_F(NamePoolTest, insert_local_defined_Symbol) {
64   const char* name = "Hello MCLinker";
65   bool isDyn = false;
66   ResolveInfo::Type type = ResolveInfo::Function;
67   ResolveInfo::Desc desc = ResolveInfo::Define;
68   ResolveInfo::Binding binding = ResolveInfo::Local;
69   uint64_t value = 0;
70   uint64_t size = 0;
71   ResolveInfo::Visibility other = ResolveInfo::Default;
72   Resolver::Result result1;
73   m_pTestee->insertSymbol(
74       name, isDyn, type, desc, binding, size, other, NULL, result1);
75 
76   EXPECT_NE(name, result1.info->name());
77   EXPECT_STREQ(name, result1.info->name());
78   EXPECT_EQ(isDyn, result1.info->isDyn());
79   EXPECT_EQ(type, result1.info->type());
80   EXPECT_EQ(desc, result1.info->desc());
81   EXPECT_EQ(binding, result1.info->binding());
82   EXPECT_EQ(size, result1.info->size());
83   EXPECT_EQ(other, result1.info->visibility());
84 
85   Resolver::Result result2;
86   m_pTestee->insertSymbol(
87       name, isDyn, type, desc, binding, size, other, NULL, result2);
88 
89   EXPECT_NE(name, result1.info->name());
90   EXPECT_STREQ(name, result1.info->name());
91   EXPECT_EQ(isDyn, result1.info->isDyn());
92   EXPECT_EQ(type, result1.info->type());
93   EXPECT_EQ(desc, result1.info->desc());
94   EXPECT_EQ(binding, result1.info->binding());
95   EXPECT_EQ(size, result1.info->size());
96   EXPECT_EQ(other, result1.info->visibility());
97 
98   EXPECT_NE(result1.existent, result2.existent);
99 }
100 
TEST_F(NamePoolTest,insert_global_reference_Symbol)101 TEST_F(NamePoolTest, insert_global_reference_Symbol) {
102   const char* name = "Hello MCLinker";
103   bool isDyn = false;
104   ResolveInfo::Type type = ResolveInfo::NoType;
105   ResolveInfo::Desc desc = ResolveInfo::Undefined;
106   ResolveInfo::Binding binding = ResolveInfo::Global;
107   uint64_t size = 0;
108   ResolveInfo::Visibility other = ResolveInfo::Default;
109   Resolver::Result result1;
110   m_pTestee->insertSymbol(
111       name, isDyn, type, desc, binding, size, other, NULL, result1);
112 
113   EXPECT_NE(name, result1.info->name());
114   EXPECT_STREQ(name, result1.info->name());
115   EXPECT_EQ(isDyn, result1.info->isDyn());
116   EXPECT_EQ(type, result1.info->type());
117   EXPECT_EQ(desc, result1.info->desc());
118   EXPECT_EQ(binding, result1.info->binding());
119   EXPECT_EQ(size, result1.info->size());
120   EXPECT_EQ(other, result1.info->visibility());
121 
122   Resolver::Result result2;
123   m_pTestee->insertSymbol(
124       name, isDyn, type, desc, binding, size, other, NULL, result2);
125 
126   EXPECT_EQ(result1.info, result2.info);
127 
128   Resolver::Result result3;
129   m_pTestee->insertSymbol("Different Symbol",
130                           isDyn,
131                           type,
132                           desc,
133                           binding,
134                           size,
135                           other,
136                           NULL,
137                           result3);
138 
139   EXPECT_NE(result1.info, result3.info);
140 }
141 
TEST_F(NamePoolTest,insertSymbol_after_insert_same_string)142 TEST_F(NamePoolTest, insertSymbol_after_insert_same_string) {
143   const char* name = "Hello MCLinker";
144   bool isDyn = false;
145   LDSymbol::Type type = LDSymbol::Defined;
146   LDSymbol::Binding binding = LDSymbol::Global;
147   const llvm::MCSectionData* section = 0;
148   uint64_t value = 0;
149   uint64_t size = 0;
150   uint8_t other = 0;
151 
152   const char* result1 = m_pTestee->insertString(name);
153   LDSymbol* sym = m_pTestee->insertSymbol(
154       name, isDyn, type, binding, section, value, size, other);
155 
156   EXPECT_STREQ(name, sym->name());
157   EXPECT_EQ(result1, sym->name());
158 
159   char s[16];
160   strcpy(s, result1);
161   const char* result2 = m_pTestee->insertString(result1);
162   const char* result3 = m_pTestee->insertString(s);
163 
164   EXPECT_EQ(result1, result2);
165   EXPECT_EQ(result1, result3);
166 }
167 
TEST_F(NamePoolTest,insert_16384_weak_reference_symbols)168 TEST_F(NamePoolTest, insert_16384_weak_reference_symbols) {
169   char name[16];
170   bool isDyn = false;
171   LDSymbol::Type type = LDSymbol::Reference;
172   LDSymbol::Binding binding = LDSymbol::Weak;
173   const llvm::MCSectionData* section = 0;
174   uint64_t value = 0;
175   uint64_t size = 0;
176   uint8_t other = 0;
177   strcpy(name, "Hello MCLinker");
178   LDSymbol* syms[128][128];
179   for (int i = 0; i < 128; ++i) {
180     name[0] = i;
181     for (int j = 0; j < 128; ++j) {
182       name[1] = j;
183       syms[i][j] = m_pTestee->insertSymbol(
184           name, isDyn, type, binding, section, value, size, other);
185 
186       ASSERT_STREQ(name, syms[i][j]->name());
187     }
188   }
189   for (int i = 127; i >= 0; --i) {
190     name[0] = i;
191     for (int j = 0; j < 128; ++j) {
192       name[1] = j;
193       LDSymbol* sym = m_pTestee->insertSymbol(
194           name, isDyn, type, binding, section, value, size, other);
195       ASSERT_EQ(sym, syms[i][j]);
196     }
197   }
198   for (int i = 0; i < 128; ++i) {
199     name[0] = i;
200     for (int j = 0; j < 128; ++j) {
201       name[1] = j;
202       LDSymbol* sym = m_pTestee->insertSymbol(
203           name, isDyn, type, binding, section, value, size, other);
204       ASSERT_EQ(sym, syms[i][j]);
205     }
206   }
207 }
208