]>
git.proxmox.com Git - rustc.git/blob - src/compiler-rt/test/esan/Unit/hashtable.cpp
1 // RUN: %clangxx_unit -esan-instrument-loads-and-stores=0 -O0 %s -o %t 2>&1
2 // RUN: %env_esan_opts="record_snapshots=0" %run %t 2>&1 | FileCheck %s
4 #include "esan/esan_hashtable.h"
12 MyData(const char *Str
) : RefCount(0) { Buf
= strdup(Str
); }
14 fprintf(stderr
, " Destructor: %s.\n", Buf
);
17 bool operator==(MyData
&Cmp
) { return strcmp(Buf
, Cmp
.Buf
) == 0; }
18 operator size_t() const {
20 for (int i
= 0; i
< strlen(Buf
); ++i
)
28 // We use a smart pointer wrapper to free the payload on hashtable removal.
29 struct MyDataPayload
{
30 MyDataPayload() : Data(nullptr) {}
31 explicit MyDataPayload(MyData
*Data
) : Data(Data
) { ++Data
->RefCount
; }
33 if (Data
&& --Data
->RefCount
== 0) {
34 fprintf(stderr
, "Deleting %s.\n", Data
->Buf
);
38 MyDataPayload(const MyDataPayload
&Copy
) {
42 MyDataPayload
& operator=(const MyDataPayload
&Copy
) {
44 this->~MyDataPayload();
50 bool operator==(MyDataPayload
&Cmp
) { return *Data
== *Cmp
.Data
; }
51 operator size_t() const { return (size_t)*Data
; }
57 __esan::HashTable
<int, int> IntTable
;
58 assert(IntTable
.size() == 0);
60 // Test iteration on an empty table.
62 for (auto Iter
= IntTable
.begin(); Iter
!= IntTable
.end();
68 bool Added
= IntTable
.add(4, 42);
70 assert(!IntTable
.add(4, 42));
71 assert(IntTable
.size() == 1);
73 bool Found
= IntTable
.lookup(4, Value
);
74 assert(Found
&& Value
== 42);
78 for (auto Iter
= IntTable
.begin(); Iter
!= IntTable
.end();
80 assert((*Iter
).Key
== 4);
81 assert((*Iter
).Data
== 42);
85 assert(Count
== IntTable
.size());
86 assert(!IntTable
.remove(5));
87 assert(IntTable
.remove(4));
89 // Test a more complex payload.
90 __esan::HashTable
<int, MyDataPayload
> DataTable(4);
91 MyDataPayload
NewData(new MyData("mystring"));
92 Added
= DataTable
.add(4, NewData
);
94 MyDataPayload FoundData
;
95 Found
= DataTable
.lookup(4, FoundData
);
96 assert(Found
&& strcmp(FoundData
.Data
->Buf
, "mystring") == 0);
97 assert(!DataTable
.remove(5));
98 assert(DataTable
.remove(4));
100 for (int i
= 0; i
< 4; ++i
) {
101 MyDataPayload
MoreData(new MyData("delete-at-end"));
102 Added
= DataTable
.add(i
+1, MoreData
);
104 assert(!DataTable
.add(i
+1, MoreData
));
106 for (int i
= 0; i
< 4; ++i
) {
107 Found
= DataTable
.lookup(i
+1, FoundData
);
108 assert(Found
&& strcmp(FoundData
.Data
->Buf
, "delete-at-end") == 0);
112 for (auto Iter
= DataTable
.begin(); Iter
!= DataTable
.end();
114 int Key
= (*Iter
).Key
;
115 FoundData
= (*Iter
).Data
;
116 assert(Key
>= 1 && Key
<= 4);
117 assert(strcmp(FoundData
.Data
->Buf
, "delete-at-end") == 0);
121 assert(Count
== DataTable
.size());
123 // Ensure the iterator supports a range-based for loop.
126 for (auto Pair
: DataTable
) {
127 assert(Pair
.Key
>= 1 && Pair
.Key
<= 4);
128 assert(strcmp(Pair
.Data
.Data
->Buf
, "delete-at-end") == 0);
133 assert(Count
== DataTable
.size());
135 // Test payload freeing via smart pointer wrapper.
136 __esan::HashTable
<MyDataPayload
, MyDataPayload
, true> DataKeyTable
;
137 MyDataPayload
DataA(new MyData("string AB"));
139 Added
= DataKeyTable
.add(DataA
, DataA
);
141 Found
= DataKeyTable
.lookup(DataA
, FoundData
);
142 assert(Found
&& strcmp(FoundData
.Data
->Buf
, "string AB") == 0);
143 MyDataPayload
DataB(new MyData("string AB"));
144 Added
= DataKeyTable
.add(DataB
, DataB
);
146 DataKeyTable
.remove(DataB
); // Should free the DataA payload.
147 DataKeyTable
.unlock();
149 // Test custom functors.
151 size_t operator()(int Key
) const { return Key
% 4; }
154 bool operator()(int Key1
, int Key2
) const { return Key1
%4 == Key2
% 4; }
156 __esan::HashTable
<int, int, false, CustomHash
, CustomEqual
> ModTable
;
157 Added
= ModTable
.add(2, 42);
159 Added
= ModTable
.add(6, 42);
162 fprintf(stderr
, "All checks passed.\n");
165 // CHECK: Deleting mystring.
166 // CHECK-NEXT: Destructor: mystring.
167 // CHECK-NEXT: All checks passed.
168 // CHECK-NEXT: Deleting string AB.
169 // CHECK-NEXT: Destructor: string AB.
170 // CHECK-NEXT: Deleting string AB.
171 // CHECK-NEXT: Destructor: string AB.
172 // CHECK-NEXT: Deleting delete-at-end.
173 // CHECK-NEXT: Destructor: delete-at-end.
174 // CHECK-NEXT: Deleting delete-at-end.
175 // CHECK-NEXT: Destructor: delete-at-end.
176 // CHECK-NEXT: Deleting delete-at-end.
177 // CHECK-NEXT: Destructor: delete-at-end.
178 // CHECK-NEXT: Deleting delete-at-end.
179 // CHECK-NEXT: Destructor: delete-at-end.