]>
Commit | Line | Data |
---|---|---|
4e0938ef | 1 | /* |
4ac4a490 | 2 | * Copyright (C) 1996-2017 The Squid Software Foundation and contributors |
4e0938ef AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
b67e2c8c | 9 | /* |
b67e2c8c | 10 | * based on ftp://ftp.cs.cmu.edu/user/sleator/splaying/top-down-splay.c |
11 | * http://bobo.link.cs.cmu.edu/cgi-bin/splay/splay-cgi.pl | |
12 | */ | |
13 | ||
f7f3304a | 14 | #include "squid.h" |
61bf2627 AJ |
15 | #include "splay.h" |
16 | #include "util.h" | |
b67e2c8c | 17 | |
074d6a40 | 18 | #include <cstdlib> |
b67e2c8c | 19 | #if HAVE_UNISTD_H |
20 | #include <unistd.h> | |
21 | #endif | |
61bf2627 | 22 | #include <random> |
42a503bd | 23 | |
24 | class intnode | |
25 | { | |
26 | ||
27 | public: | |
26ac0430 | 28 | intnode() : i(0) {} |
42a503bd | 29 | |
30 | intnode (int anInt) : i (anInt) {} | |
31 | ||
b67e2c8c | 32 | int i; |
42a503bd | 33 | }; |
b67e2c8c | 34 | |
35 | int | |
29b17d63 | 36 | compareintvoid(void * const &a, void * const &n) |
b67e2c8c | 37 | { |
38 | intnode *A = (intnode *)a; | |
39 | intnode *B = (intnode *)n; | |
b67e2c8c | 40 | return A->i - B->i; |
41 | } | |
42 | ||
29b17d63 | 43 | int |
44 | compareint(intnode * const &a, intnode * const &b) | |
45 | { | |
46 | return a->i - b->i; | |
47 | } | |
48 | ||
23087cb8 | 49 | class SplayCheck |
50 | { | |
42a503bd | 51 | |
52 | public: | |
23087cb8 | 53 | static void BeginWalk(); |
54 | static int LastValue; | |
55 | static bool ExpectedFail; | |
56 | static void WalkVoid(void *const &, void *); | |
57 | static void WalkNode(intnode *const &, void *); | |
58 | static void WalkNodeRef(intnode const &, void *); | |
59 | static void CheckNode(intnode const &); | |
60 | }; | |
61 | ||
62 | int SplayCheck::LastValue (0); | |
63 | bool SplayCheck::ExpectedFail (false); | |
64 | ||
b67e2c8c | 65 | void |
23087cb8 | 66 | SplayCheck::BeginWalk() |
b67e2c8c | 67 | { |
23087cb8 | 68 | LastValue = 0; |
b67e2c8c | 69 | } |
70 | ||
29b17d63 | 71 | void |
23087cb8 | 72 | SplayCheck::WalkVoid(void *const &node, void *state) |
29b17d63 | 73 | { |
23087cb8 | 74 | intnode *A = (intnode *)node; |
75 | CheckNode(*A); | |
76 | } | |
77 | ||
78 | void | |
79 | SplayCheck::CheckNode(intnode const &A) | |
80 | { | |
81 | if (LastValue > A.i) { | |
42a503bd | 82 | /* failure */ |
83 | ||
84 | if (!ExpectedFail) | |
85 | exit (1); | |
23087cb8 | 86 | } else |
42a503bd | 87 | /* success */ |
88 | if (ExpectedFail) | |
89 | exit (1); | |
90 | ||
23087cb8 | 91 | LastValue = A.i; |
92 | } | |
93 | ||
94 | void | |
95 | SplayCheck::WalkNode (intnode *const &a, void *state) | |
96 | { | |
97 | CheckNode (*a); | |
98 | } | |
99 | ||
100 | void | |
101 | SplayCheck::WalkNodeRef (intnode const &a, void *state) | |
102 | { | |
103 | CheckNode (a); | |
29b17d63 | 104 | } |
105 | ||
106 | void | |
107 | destintvoid(void * &data) | |
108 | { | |
109 | intnode *i = (intnode *)data; | |
110 | xfree (i); | |
111 | } | |
112 | ||
113 | void | |
114 | destint(intnode * &data) | |
115 | { | |
116 | delete data; | |
117 | } | |
118 | ||
119 | int | |
120 | compareintref(intnode const &a, intnode const &b) | |
121 | { | |
122 | return a.i - b.i; | |
123 | } | |
124 | ||
29b17d63 | 125 | void |
126 | destintref (intnode &) | |
42a503bd | 127 | {} |
29b17d63 | 128 | |
b67e2c8c | 129 | int |
130 | main(int argc, char *argv[]) | |
131 | { | |
61bf2627 | 132 | std::mt19937 generator; |
8ed8fa40 | 133 | xuniform_int_distribution<int> distribution; |
61bf2627 AJ |
134 | auto nextRandom = std::bind (distribution, generator); |
135 | ||
42a503bd | 136 | { |
42a503bd | 137 | /* test void * splay containers */ |
138 | splayNode *top = NULL; | |
42a503bd | 139 | |
61bf2627 AJ |
140 | for (int i = 0; i < 100; ++i) { |
141 | intnode *I = (intnode *)xcalloc(sizeof(intnode), 1); | |
142 | I->i = nextRandom(); | |
bf0e740b FC |
143 | if (top) |
144 | top = top->insert(I, compareintvoid); | |
145 | else | |
146 | top = new splayNode(static_cast<void*>(new intnode(101))); | |
42a503bd | 147 | } |
148 | ||
149 | SplayCheck::BeginWalk(); | |
b001e822 | 150 | top->walk(SplayCheck::WalkVoid, NULL); |
42a503bd | 151 | |
152 | SplayCheck::BeginWalk(); | |
153 | top->walk(SplayCheck::WalkVoid, NULL); | |
154 | top->destroy(destintvoid); | |
29b17d63 | 155 | } |
42a503bd | 156 | |
29b17d63 | 157 | /* test typesafe splay containers */ |
42a503bd | 158 | { |
159 | /* intnode* */ | |
bf0e740b | 160 | SplayNode<intnode *> *safeTop = new SplayNode<intnode *>(new intnode(101)); |
42a503bd | 161 | |
14942edd | 162 | for ( int i = 0; i < 100; ++i) { |
42a503bd | 163 | intnode *I; |
164 | I = new intnode; | |
61bf2627 | 165 | I->i = nextRandom(); |
42a503bd | 166 | safeTop = safeTop->insert(I, compareint); |
167 | } | |
168 | ||
169 | SplayCheck::BeginWalk(); | |
170 | safeTop->walk(SplayCheck::WalkNode, NULL); | |
171 | ||
172 | safeTop->destroy(destint); | |
29b17d63 | 173 | } |
42a503bd | 174 | { |
175 | /* intnode */ | |
bf0e740b | 176 | SplayNode<intnode> *safeTop = new SplayNode<intnode>(101); |
42a503bd | 177 | |
14942edd | 178 | for (int i = 0; i < 100; ++i) { |
42a503bd | 179 | intnode I; |
61bf2627 | 180 | I.i = nextRandom(); |
42a503bd | 181 | safeTop = safeTop->insert(I, compareintref); |
182 | } | |
183 | ||
184 | SplayCheck::BeginWalk(); | |
185 | safeTop->walk(SplayCheck::WalkNodeRef, NULL); | |
186 | ||
187 | safeTop->destroy(destintref); | |
b67e2c8c | 188 | } |
9dca980d | 189 | |
23087cb8 | 190 | /* check the check routine */ |
9dca980d AJ |
191 | { |
192 | SplayCheck::BeginWalk(); | |
193 | intnode I; | |
194 | I.i = 1; | |
195 | /* check we don't segfault on NULL splay calls */ | |
196 | SplayCheck::WalkNodeRef(I, NULL); | |
197 | I.i = 0; | |
198 | SplayCheck::ExpectedFail = true; | |
199 | SplayCheck::WalkNodeRef(I, NULL); | |
200 | } | |
42a503bd | 201 | |
4c50505b | 202 | { |
42a503bd | 203 | /* check for begin() */ |
bf0e740b | 204 | Splay<intnode> *safeTop = new Splay<intnode>(); |
42a503bd | 205 | |
206 | if (safeTop->start() != NULL) | |
207 | exit (1); | |
208 | ||
ccd33084 | 209 | if (safeTop->finish() != NULL) |
42a503bd | 210 | exit (1); |
211 | ||
14942edd | 212 | for (int i = 0; i < 100; ++i) { |
42a503bd | 213 | intnode I; |
61bf2627 | 214 | I.i = nextRandom(); |
42a503bd | 215 | |
216 | if (I.i > 50 && I.i < 10000000) | |
bf0e740b | 217 | safeTop->insert(I, compareintref); |
42a503bd | 218 | } |
219 | ||
220 | { | |
221 | intnode I; | |
222 | I.i = 50; | |
bf0e740b | 223 | safeTop->insert (I, compareintref); |
42a503bd | 224 | I.i = 10000000; |
bf0e740b | 225 | safeTop->insert (I, compareintref); |
42a503bd | 226 | } |
227 | ||
228 | if (!safeTop->start()) | |
229 | exit (1); | |
230 | ||
231 | if (safeTop->start()->data.i != 50) | |
232 | exit (1); | |
233 | ||
ccd33084 | 234 | if (!safeTop->finish()) |
42a503bd | 235 | exit (1); |
236 | ||
ccd33084 | 237 | if (safeTop->finish()->data.i != 10000000) |
42a503bd | 238 | exit (1); |
239 | ||
240 | safeTop->destroy(destintref); | |
4c50505b | 241 | } |
42a503bd | 242 | |
4c50505b | 243 | { |
42a503bd | 244 | Splay<intnode *> aSplay; |
245 | ||
246 | if (aSplay.start() != NULL) | |
247 | exit (1); | |
248 | ||
249 | if (aSplay.size() != 0) | |
250 | exit (1); | |
251 | ||
252 | aSplay.insert (new intnode(5), compareint); | |
253 | ||
254 | if (aSplay.start() == NULL) | |
255 | exit (1); | |
256 | ||
257 | if (aSplay.size() != 1) | |
258 | exit (1); | |
259 | ||
260 | aSplay.destroy(destint); | |
261 | ||
262 | if (aSplay.start() != NULL) | |
263 | exit (1); | |
264 | ||
265 | if (aSplay.size() != 0) | |
266 | exit (1); | |
4c50505b | 267 | } |
42a503bd | 268 | |
cb1e2244 | 269 | /* TODO: also test the other Splay API */ |
bf0e740b | 270 | |
b67e2c8c | 271 | return 0; |
272 | } | |
f53969cc | 273 |