VirtualBox

source: vbox/trunk/src/VBox/Runtime/testcase/tstIprtList.cpp@ 53402

Last change on this file since 53402 was 45520, checked in by vboxsync, 12 years ago

iprt/cpp/list.h,iprt/cpp/mtlist.h: Added assertions for index out of range conditions and tried to force those cases to have predictable non-destructive behavior. (Not possible when indexing an empty list, unfortunately.) Fixed RTMemRealloc bugs. Added missing read locking. Also changed the testcase to not wait forever in the multithreaded test2() function.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 26.7 KB
Line 
1/* $Id: tstIprtList.cpp 45520 2013-04-12 14:22:41Z vboxsync $ */
2/** @file
3 * IPRT Testcase - RTCList/RTCMTList.
4 */
5
6/*
7 * Copyright (C) 2011 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27/*******************************************************************************
28* Header Files *
29*******************************************************************************/
30#include <iprt/cpp/mtlist.h>
31
32#include <iprt/cpp/ministring.h>
33#include <iprt/test.h>
34#include <iprt/rand.h>
35#include <iprt/thread.h>
36#include <iprt/time.h>
37
38
39/*******************************************************************************
40* Global Variables *
41*******************************************************************************/
42/** Used for the string test. */
43static const char *g_apszTestStrings[] =
44{
45 "Lorem ipsum dolor sit amet, consectetur adipiscing elit.",
46 "Vestibulum non turpis vel metus pellentesque tincidunt at id massa.",
47 "Cras quis erat sed nulla ullamcorper molestie.",
48 "Mauris ac elit turpis, id pulvinar diam.",
49 "Nulla quis dolor dolor, in ultrices diam.",
50 "Vivamus ac quam non ipsum vehicula tempor ac ac arcu.",
51 "Aenean posuere lacus blandit erat semper eu iaculis ante eleifend.",
52 "Donec quis quam a lacus interdum sollicitudin quis eu est.",
53 "Morbi sed nisi a arcu commodo convallis.",
54 "Aenean molestie condimentum velit, non mattis magna ultricies quis.",
55 "Nulla id velit at mauris gravida mattis.",
56 "Phasellus viverra velit eu urna semper in porta arcu sollicitudin.",
57 "Pellentesque consequat turpis et tortor hendrerit id tempor ipsum lacinia.",
58 "Cras iaculis nulla quis risus pulvinar eget tempor lectus placerat.",
59 "Nullam in nulla sed sapien euismod euismod.",
60 "Morbi in tortor at magna sagittis fermentum ut eu nunc.",
61 "Nulla vitae ante sit amet dui molestie sagittis lacinia quis tellus.",
62 "Proin iaculis lorem ultricies metus bibendum tincidunt.",
63 "Sed gravida purus id risus sollicitudin ac porta orci vestibulum.",
64 "Duis quis purus non ligula consectetur cursus eu interdum erat.",
65 "Nullam non nunc in elit volutpat tempor in nec metus.",
66 "Aliquam id purus eget enim luctus molestie.",
67 "Sed id elit nec elit luctus scelerisque.",
68 "Suspendisse viverra leo non ligula congue ac luctus nisl vulputate.",
69 "Nulla dignissim lobortis nunc, eu tempus ipsum luctus sed.",
70 "Integer vel lacus lacus, quis condimentum felis.",
71 "Nulla ut lacus ac lacus gravida ultrices id sed ipsum.",
72 "Etiam non purus ut augue fermentum consequat.",
73 "Nam sit amet eros quis nibh blandit lacinia non posuere lectus.",
74 "Sed sit amet ipsum et dolor sagittis facilisis.",
75 "Ut congue nisi lacus, vel ultrices est.",
76 "Donec vel erat ut justo hendrerit sodales eu eget libero.",
77 "Integer a ipsum ac nunc eleifend congue convallis a urna.",
78 "Sed vel eros eu lectus imperdiet vehicula.",
79 "Vivamus eget turpis sed erat dapibus varius eget eu nulla.",
80 "Nam id nulla non elit eleifend commodo sed ac est.",
81 "Integer pulvinar dolor sodales velit pulvinar et facilisis eros scelerisque.",
82 "Ut mattis arcu ut libero imperdiet in rhoncus augue sodales.",
83 "Ut luctus turpis ligula, id dapibus felis.",
84 "Nullam sit amet sapien eget tellus hendrerit vestibulum eget in odio.",
85 "Phasellus non orci vitae mi placerat semper.",
86 "Quisque pharetra aliquet velit, quis tempor magna porttitor nec.",
87 "Praesent porta neque felis, vehicula facilisis odio.",
88 "Maecenas ultricies ipsum eu velit laoreet faucibus.",
89 "Mauris et nunc leo, et euismod quam.",
90 "Phasellus a felis et justo fringilla lacinia.",
91 "Vestibulum eget augue ante, ac viverra neque.",
92 "Mauris pellentesque ligula quis metus elementum venenatis.",
93 "Curabitur eu neque tellus, non porta sapien.",
94 "Ut mattis metus id enim aliquam laoreet et sed tortor.",
95 "Aenean quis nulla vitae nulla auctor lobortis a egestas turpis.",
96 "Praesent vitae ante a urna porta placerat non nec eros.",
97 "Donec quis neque eros, placerat adipiscing turpis.",
98 "Cras sit amet sapien risus, quis euismod arcu.",
99 "Integer volutpat massa eros, ac gravida mi.",
100 "Nunc vitae nunc sagittis diam vulputate suscipit.",
101 "Suspendisse quis mauris bibendum mauris aliquet pulvinar.",
102 "Donec volutpat vestibulum ligula, eget interdum tortor malesuada sit amet.",
103 "Mauris hendrerit dui non nibh varius sit amet fringilla orci pretium.",
104 "Phasellus a quam tellus, auctor lacinia sapien.",
105 "Sed dapibus leo vitae neque faucibus id porttitor sapien ultricies.",
106 "Maecenas euismod elit nec tortor sagittis pretium.",
107 "Ut tincidunt risus at erat fermentum sit amet molestie ante lacinia.",
108 "Nulla non leo nec lacus sollicitudin lobortis a a nisl.",
109 "Nunc vulputate erat vel libero elementum a interdum turpis malesuada.",
110 "Morbi id libero turpis, a lobortis dolor.",
111 "Donec vehicula imperdiet lorem, non pretium nulla tempus ut.",
112 "Morbi lacinia massa id nunc tempus in blandit risus blandit.",
113 "Sed feugiat orci id ipsum suscipit quis fringilla enim rutrum.",
114 "Mauris suscipit lobortis urna, vel dictum justo iaculis ac.",
115 "In rhoncus lectus tristique nunc blandit gravida placerat turpis rutrum.",
116 "Aliquam pellentesque ornare justo, sed hendrerit metus mattis a.",
117 "Nam aliquet lorem congue nisl blandit posuere.",
118 "Sed lobortis interdum ipsum, ac cursus erat lacinia in.",
119 "Maecenas vel tortor vel lorem facilisis interdum.",
120 "Aenean porttitor massa enim, eget dignissim est.",
121 "Nullam id libero lacus, mattis feugiat risus.",
122 "Fusce et dolor at eros ornare auctor malesuada vel ipsum.",
123 "Donec at massa sit amet lorem pellentesque interdum at ac lacus.",
124 "Praesent suscipit velit at justo suscipit eu vestibulum ligula interdum.",
125 "Aenean id justo nulla, vitae vulputate diam.",
126 "Fusce pellentesque leo quis orci pulvinar at pellentesque tellus dictum.",
127 "Ut facilisis purus at enim varius vulputate.",
128 "Donec malesuada bibendum sapien, sed pretium nisi cursus quis.",
129 "Mauris porttitor diam ut sapien pretium egestas.",
130 "Vestibulum ut justo eu libero semper convallis vitae et velit.",
131 "Quisque eleifend dapibus ligula, eu tincidunt massa rutrum at.",
132 "Sed euismod diam eget enim suscipit dictum.",
133 "Mauris fermentum orci eu nunc venenatis in sollicitudin tellus vestibulum.",
134 "Vivamus faucibus consequat turpis, lobortis vehicula lectus gravida eget.",
135 "Curabitur eu erat eu mi interdum scelerisque.",
136 "Morbi consequat molestie nulla, imperdiet elementum augue sagittis vel.",
137 "Sed ullamcorper velit suscipit arcu egestas quis commodo est hendrerit.",
138 "Proin vitae velit ut enim sollicitudin ultrices.",
139 "Curabitur posuere euismod lacus, sed volutpat erat adipiscing sit amet.",
140 "Cras sit amet sem lorem, in cursus augue.",
141 "Sed fermentum ultricies orci, quis hendrerit risus imperdiet et.",
142 "Proin nec arcu interdum ipsum molestie vestibulum.",
143 "Nulla quis quam non sem pretium scelerisque et eu velit.",
144 "Donec eu tellus nisl, ac vehicula tortor."
145};
146
147
148/**
149 * Does a list test.
150 *
151 * @param T1 The list type.
152 * @param T2 The input type
153 * @param pcszDesc The test description.
154 * @param paTestData Pointer to the array with the test input data.
155 * @param cTestItems The size of the input data.
156 */
157template<template <class, typename> class L, typename T1, typename T2, typename T3>
158static void test1(const char *pcszDesc, T3 paTestData[], size_t cTestItems)
159{
160 RTTestISubF("%s with size of %u (items=%u)", pcszDesc, sizeof(T1), cTestItems);
161
162 /*
163 * Construction
164 */
165
166 /* Create a test list */
167 L<T1, T2> testList;
168
169 const size_t defCap = L<T1, T2>::kDefaultCapacity;
170 RTTESTI_CHECK(testList.isEmpty());
171 RTTESTI_CHECK(testList.size() == 0);
172 RTTESTI_CHECK(testList.capacity() == defCap);
173
174 /*
175 * Adding
176 */
177
178 /* Add the second half of the test data */
179 size_t cAdded = 1;
180
181 /* Start adding the second half of our test list */
182 for (size_t i = cTestItems / 2; i < cTestItems; ++i, ++cAdded)
183 {
184 testList.append(paTestData[i]);
185 RTTESTI_CHECK_RETV(testList.size() == cAdded);
186 RTTESTI_CHECK(testList.at(0) == paTestData[cTestItems / 2]);
187 RTTESTI_CHECK(testList[0] == paTestData[cTestItems / 2]);
188 RTTESTI_CHECK(testList.first() == paTestData[cTestItems / 2]);
189 RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[i]);
190 RTTESTI_CHECK(testList[cAdded - 1] == paTestData[i]);
191 RTTESTI_CHECK(testList.last() == paTestData[i]);
192 }
193
194 /* Check that all is correctly appended. */
195 RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2);
196 RTTESTI_CHECK_RETV(testList.isEmpty() == false);
197 for (size_t i = 0; i < testList.size(); ++i)
198 RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]);
199
200 /* Start prepending the first half of our test list. Iterate reverse to get
201 * the correct sorting back. */
202 for (size_t i = cTestItems / 2; i > 0; --i, ++cAdded)
203 {
204 testList.prepend(paTestData[i - 1]);
205 RTTESTI_CHECK_RETV(testList.size() == cAdded);
206 RTTESTI_CHECK(testList.at(0) == paTestData[i - 1]);
207 RTTESTI_CHECK(testList[0] == paTestData[i - 1]);
208 RTTESTI_CHECK(testList.first() == paTestData[i - 1]);
209 RTTESTI_CHECK(testList.at(cAdded - 1) == paTestData[cTestItems - 1]);
210 RTTESTI_CHECK(testList[cAdded - 1] == paTestData[cTestItems - 1]);
211 RTTESTI_CHECK(testList.last() == paTestData[cTestItems - 1]);
212 }
213
214 /* Check that all is correctly prepended. */
215 RTTESTI_CHECK_RETV(testList.size() == cTestItems);
216 RTTESTI_CHECK_RETV(testList.isEmpty() == false);
217 for (size_t i = 0; i < testList.size(); ++i)
218 RTTESTI_CHECK(testList.at(i) == paTestData[i]);
219
220 /*
221 * Contains
222 */
223 L<T1, T2> testList2;
224
225 /* Check full list. */
226 RTTESTI_CHECK( testList.contains(paTestData[0]));
227 RTTESTI_CHECK( testList.contains(paTestData[cTestItems / 2]));
228 RTTESTI_CHECK( testList.contains(paTestData[cTestItems - 1]));
229 RTTESTI_CHECK(!testList.contains(T1()));
230 /* Check empty list. */
231 RTTESTI_CHECK(!testList2.contains(paTestData[0]));
232 RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems / 2]));
233 RTTESTI_CHECK(!testList2.contains(paTestData[cTestItems - 1]));
234 RTTESTI_CHECK(!testList2.contains(T1()));
235
236 /*
237 * Copy operator
238 */
239 L<T1, T2> testList3(testList);
240
241 /* Check that all is correctly appended. */
242 RTTESTI_CHECK_RETV(testList3.size() == cTestItems);
243 for (size_t i = 0; i < testList3.size(); ++i)
244 RTTESTI_CHECK(testList3.at(i) == paTestData[i]);
245
246 /*
247 * "=" operator
248 */
249 L<T1, T2> testList4;
250 testList4 = testList;
251
252 /* Check that all is correctly appended. */
253 RTTESTI_CHECK_RETV(testList4.size() == cTestItems);
254 for (size_t i = 0; i < testList4.size(); ++i)
255 RTTESTI_CHECK(testList4.at(i) == paTestData[i]);
256
257 /*
258 * Append list
259 */
260 testList3.append(testList4);
261
262 /* Check that all is correctly appended. */
263 RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2);
264 for (size_t i = 0; i < testList3.size(); ++i)
265 RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]);
266
267 /*
268 * Prepend list
269 */
270 testList3.prepend(testList4);
271
272 /* Check that all is correctly appended. */
273 RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 3);
274 for (size_t i = 0; i < testList3.size(); ++i)
275 RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]);
276
277 /*
278 * "value" method
279 */
280 for (size_t i = 0; i < testList3.size(); ++i)
281 RTTESTI_CHECK(testList3.value(i) == paTestData[i % cTestItems]);
282 for (size_t i = 0; i < testList3.size(); ++i)
283 RTTESTI_CHECK(testList3.value(i, T1()) == paTestData[i % cTestItems]);
284 RTTESTI_CHECK(testList3.value(testList3.size() + 1) == T1()); /* Invalid index */
285 RTTESTI_CHECK(testList3.value(testList3.size() + 1, T1()) == T1()); /* Invalid index */
286
287 /*
288 * operator[] (reading)
289 */
290 for (size_t i = 0; i < testList.size(); ++i)
291 RTTESTI_CHECK(testList[i] == paTestData[i]);
292
293 /*
294 * operator[] (writing)
295 *
296 * Replace with inverted array.
297 */
298 for (size_t i = 0; i < cTestItems; ++i)
299 testList[i] = paTestData[cTestItems - i - 1];
300 RTTESTI_CHECK_RETV(testList.size() == cTestItems);
301 for (size_t i = 0; i < testList.size(); ++i)
302 RTTESTI_CHECK(testList[i] == paTestData[cTestItems - i - 1]);
303
304 /*
305 * Replace
306 *
307 * Replace with inverted array (Must be original array when finished).
308 */
309 for (size_t i = 0; i < cTestItems; ++i)
310 testList.replace(i, paTestData[i]);
311 RTTESTI_CHECK_RETV(testList.size() == cTestItems);
312 for (size_t i = 0; i < testList.size(); ++i)
313 RTTESTI_CHECK(testList[i] == paTestData[i]);
314
315 /*
316 * Removing
317 */
318
319 /* Remove Range */
320 testList3.removeRange(cTestItems, cTestItems * 2);
321 RTTESTI_CHECK_RETV(testList3.size() == cTestItems * 2);
322 for (size_t i = 0; i < testList3.size(); ++i)
323 RTTESTI_CHECK(testList3.at(i) == paTestData[i % cTestItems]);
324
325 /* Remove the first half (reverse) */
326 size_t cRemoved = 1;
327 for (size_t i = cTestItems / 2; i > 0; --i, ++cRemoved)
328 {
329 testList.removeAt(i - 1);
330 RTTESTI_CHECK_RETV(testList.size() == cTestItems - cRemoved);
331 }
332 RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2);
333
334 /* Check that all is correctly removed and only the second part of the list
335 * is still there. */
336 for (size_t i = 0; i < testList.size(); ++i)
337 RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]);
338
339 /*
340 * setCapacitiy
341 */
342 testList.setCapacity(cTestItems * 5);
343 RTTESTI_CHECK(testList.capacity() == cTestItems * 5);
344 RTTESTI_CHECK_RETV(testList.size() == cTestItems / 2);
345
346 /* As the capacity just increased, we should still have all entries from
347 * the previous list. */
348 for (size_t i = 0; i < testList.size(); ++i)
349 RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]);
350
351 /* Decrease the capacity so it will be smaller than the count of items in
352 * the list. The list should be shrink automatically, but the remaining
353 * items should be still valid. */
354 testList.setCapacity(cTestItems / 4);
355 RTTESTI_CHECK_RETV(testList.size() == cTestItems / 4);
356 RTTESTI_CHECK(testList.capacity() == cTestItems / 4);
357 for (size_t i = 0; i < testList.size(); ++i)
358 RTTESTI_CHECK(testList.at(i) == paTestData[cTestItems / 2 + i]);
359
360 /* Clear all */
361 testList.clear();
362 RTTESTI_CHECK_RETV(testList.isEmpty());
363 RTTESTI_CHECK_RETV(testList.size() == 0);
364 RTTESTI_CHECK(testList.capacity() == defCap);
365
366
367 /* Copy empty lists. */
368 L<T1, T2> testList5(testList);
369 RTTESTI_CHECK_RETV(testList5.isEmpty());
370 RTTESTI_CHECK_RETV(testList5.size() == 0);
371 RTTESTI_CHECK(testList5.capacity() == 0);
372
373 testList5.append(paTestData[0]);
374 testList5 = testList;
375 RTTESTI_CHECK_RETV(testList5.isEmpty());
376 RTTESTI_CHECK_RETV(testList5.size() == 0);
377 RTTESTI_CHECK(testList5.capacity() == 0);
378
379 /*
380 * Negative testing.
381 */
382 bool fMayPanic = RTAssertMayPanic();
383 bool fQuiet = RTAssertAreQuiet();
384 RTAssertSetMayPanic(false);
385 RTAssertSetQuiet(true);
386
387 L<T1, T2> testList6;
388 for (size_t i = 0; i < cTestItems; ++i)
389 testList6.insert(i, paTestData[i]);
390 RTTESTI_CHECK(testList6.size() == cTestItems);
391
392 /* Insertion beyond the end of the array ends up at the end. */
393 size_t cBefore = testList6.size();
394 testList6.insert(cBefore + 3, paTestData[0]);
395 RTTESTI_CHECK(testList6.size() == cBefore + 1);
396 RTTESTI_CHECK(testList6.at(cBefore) == paTestData[0]);
397
398 cBefore = testList6.size();
399 L<T1, T2> testList7(testList6);
400 testList6.insert(testList6.size() + 42, testList7);
401 RTTESTI_CHECK(testList6.size() == cBefore + testList7.size());
402
403 /* Inserting, appending or prepending a list to itself is not supported. */
404 cBefore = testList6.size();
405 testList6.insert(3, testList6);
406 RTTESTI_CHECK(testList6.size() == cBefore);
407
408 cBefore = testList6.size();
409 testList6.append(testList6);
410 RTTESTI_CHECK(testList6.size() == cBefore);
411
412 cBefore = testList6.size();
413 testList6.prepend(testList6);
414 RTTESTI_CHECK(testList6.size() == cBefore);
415
416 /* Replace does nothing if the index is bad. */
417 cBefore = testList6.size();
418 testList6.replace(cBefore, testList6[6]);
419 RTTESTI_CHECK(testList6.size() == cBefore);
420
421 cBefore = testList6.size();
422 testList6.replace(cBefore + 64, testList6[6]);
423 RTTESTI_CHECK(testList6.size() == cBefore);
424
425 /* Indexing beyond the array returns the last element. */
426 cBefore = testList6.size();
427 RTTESTI_CHECK(testList6[cBefore] == testList6.last());
428 RTTESTI_CHECK(testList6[cBefore + 42] == testList6.last());
429
430 RTTESTI_CHECK(&testList6[cBefore] == &testList6[cBefore - 1]);
431 RTTESTI_CHECK(&testList6[cBefore + 42] == &testList6[cBefore - 1]);
432
433 /* removeAt does nothing if the index is bad. */
434 cBefore = testList6.size();
435 testList6.removeAt(cBefore);
436 RTTESTI_CHECK(testList6.size() == cBefore);
437
438 cBefore = testList6.size();
439 testList6.removeAt(cBefore + 42);
440 RTTESTI_CHECK(testList6.size() == cBefore);
441
442 L<T1, T2> testListEmpty1; RTTESTI_CHECK(!testListEmpty1.size());
443 testListEmpty1.removeFirst();
444 RTTESTI_CHECK(!testListEmpty1.size());
445
446 testListEmpty1.removeLast();
447 RTTESTI_CHECK(!testListEmpty1.size());
448
449 testListEmpty1.removeAt(128);
450 RTTESTI_CHECK(!testListEmpty1.size());
451
452 /* removeRange interprets indexes beyond the end as the end of array (asserted). */
453 testListEmpty1.removeRange(42, 128);
454 RTTESTI_CHECK(!testListEmpty1.size());
455
456 cBefore = testList6.size();
457 testList6.removeRange(cBefore, cBefore);
458 RTTESTI_CHECK(testList6.size() == cBefore);
459
460 cBefore = testList6.size();
461 testList6.removeRange(cBefore + 12, cBefore + 128);
462 RTTESTI_CHECK(testList6.size() == cBefore);
463
464 /* If end is less or equal to the start, nothing is done. */
465 testListEmpty1.removeRange(128, 0);
466 RTTESTI_CHECK(!testListEmpty1.size());
467
468 cBefore = testList6.size();
469 testList6.removeRange(cBefore, 0);
470 RTTESTI_CHECK(testList6.size() == cBefore);
471
472 cBefore = testList6.size();
473 testList6.removeRange(0, 0);
474 RTTESTI_CHECK(testList6.size() == cBefore);
475
476 cBefore = testList6.size();
477 testList6.removeRange(0, 0);
478 RTTESTI_CHECK(testList6.size() == cBefore);
479
480 RTAssertSetQuiet(fQuiet);
481 RTAssertSetMayPanic(fMayPanic);
482}
483
484/* define RTCList here to see what happens without MT support ;)
485 * (valgrind is the preferred tool to check). */
486#define MTTESTLISTTYPE RTCMTList
487#define MTTESTTYPE uint32_t
488#define MTTESTITEMS 1000
489
490/**
491 * Thread for prepending items to a shared list.
492 *
493 * @param hSelf The thread handle.
494 * @param pvUser The provided user data.
495 */
496static DECLCALLBACK(int) MtTest1ThreadProc(RTTHREAD hSelf, void *pvUser)
497{
498 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
499
500 /* Prepend new items at the start of the list. */
501 for (size_t i = 0; i < MTTESTITEMS; ++i)
502 pTestList->prepend(0x0);
503
504 return VINF_SUCCESS;
505}
506
507/**
508 * Thread for appending items to a shared list.
509 *
510 * @param hSelf The thread handle.
511 * @param pvUser The provided user data.
512 */
513static DECLCALLBACK(int) MtTest2ThreadProc(RTTHREAD hSelf, void *pvUser)
514{
515 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
516
517 /* Append new items at the end of the list. */
518 for (size_t i = 0; i < MTTESTITEMS; ++i)
519 pTestList->append(0xFFFFFFFF);
520
521 return VINF_SUCCESS;
522}
523
524/**
525 * Thread for inserting items to a shared list.
526 *
527 * @param hSelf The thread handle.
528 * @param pvUser The provided user data.
529 */
530static DECLCALLBACK(int) MtTest3ThreadProc(RTTHREAD hSelf, void *pvUser)
531{
532 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
533
534 /* Insert new items in the middle of the list. */
535 for (size_t i = 0; i < MTTESTITEMS; ++i)
536 pTestList->insert(pTestList->size() / 2, 0xF0F0F0F0);
537
538 return VINF_SUCCESS;
539}
540
541/**
542 * Thread for reading items from a shared list.
543 *
544 * @param hSelf The thread handle.
545 * @param pvUser The provided user data.
546 */
547static DECLCALLBACK(int) MtTest4ThreadProc(RTTHREAD hSelf, void *pvUser)
548{
549 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
550
551 MTTESTTYPE a;
552 /* Try to read C items from random places. */
553 for (size_t i = 0; i < MTTESTITEMS; ++i)
554 {
555 /* Make sure there is at least one item in the list. */
556 while (pTestList->isEmpty())
557 RTThreadYield();
558 a = pTestList->at(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1));
559 }
560
561 return VINF_SUCCESS;
562}
563
564/**
565 * Thread for replacing items in a shared list.
566 *
567 * @param hSelf The thread handle.
568 * @param pvUser The provided user data.
569 */
570static DECLCALLBACK(int) MtTest5ThreadProc(RTTHREAD hSelf, void *pvUser)
571{
572 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
573
574 /* Try to replace C items from random places. */
575 for (size_t i = 0; i < MTTESTITEMS; ++i)
576 {
577 /* Make sure there is at least one item in the list. */
578 while (pTestList->isEmpty())
579 RTThreadYield();
580 pTestList->replace(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1), 0xFF00FF00);
581 }
582
583 return VINF_SUCCESS;
584}
585
586/**
587 * Thread for erasing items from a shared list.
588 *
589 * @param hSelf The thread handle.
590 * @param pvUser The provided user data.
591 */
592static DECLCALLBACK(int) MtTest6ThreadProc(RTTHREAD hSelf, void *pvUser)
593{
594 MTTESTLISTTYPE<MTTESTTYPE> *pTestList = (MTTESTLISTTYPE<MTTESTTYPE> *)pvUser;
595
596 /* Try to delete items from random places. */
597 for (size_t i = 0; i < MTTESTITEMS; ++i)
598 {
599 /* Make sure there is at least one item in the list. */
600 while (pTestList->isEmpty())
601 RTThreadYield();
602 pTestList->removeAt(RTRandU32Ex(0, (uint32_t)pTestList->size() - 1));
603 }
604
605 return VINF_SUCCESS;
606}
607
608/**
609 * Does a multi-threading list test. Several list additions, reading, replacing
610 * and erasing are done simultaneous.
611 *
612 */
613static void test2()
614{
615 RTTestISubF("MT test with 6 threads (%u tests per thread).", MTTESTITEMS);
616
617 int rc;
618 MTTESTLISTTYPE<MTTESTTYPE> testList;
619 RTTHREAD ahThreads[6];
620 static PFNRTTHREAD apfnThreads[6] =
621 {
622 MtTest1ThreadProc, MtTest2ThreadProc, MtTest3ThreadProc, MtTest4ThreadProc, MtTest5ThreadProc, MtTest6ThreadProc
623 };
624
625 for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++)
626 {
627 RTTESTI_CHECK_RC_RETV(RTThreadCreateF(&ahThreads[i], apfnThreads[i], &testList, 0,
628 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "mttest%u", i), VINF_SUCCESS);
629 }
630
631 uint64_t tsMsDeadline = RTTimeMilliTS() + 60000;
632 for (unsigned i = 0; i < RT_ELEMENTS(ahThreads); i++)
633 {
634 uint64_t tsNow = RTTimeMilliTS();
635 uint32_t cWait = tsNow > tsMsDeadline ? 5000 : tsMsDeadline - tsNow;
636 RTTESTI_CHECK_RC(RTThreadWait(ahThreads[i], tsNow, NULL), VINF_SUCCESS);
637 }
638
639 RTTESTI_CHECK_RETV(testList.size() == MTTESTITEMS * 2);
640 for (size_t i = 0; i < testList.size(); ++i)
641 {
642 uint32_t a = testList.at(i);
643 RTTESTI_CHECK(a == 0x0 || a == 0xFFFFFFFF || a == 0xF0F0F0F0 || a == 0xFF00FF00);
644 }
645}
646
647int main()
648{
649 /* How many integer test items should be created. */
650 static const size_t s_cTestCount = 1000;
651
652 RTTEST hTest;
653 RTEXITCODE rcExit = RTTestInitAndCreate("tstIprtList", &hTest);
654 if (rcExit)
655 return rcExit;
656 RTTestBanner(hTest);
657
658 /*
659 * Native types.
660 */
661 uint8_t au8TestInts[s_cTestCount];
662 for (size_t i = 0; i < RT_ELEMENTS(au8TestInts); ++i)
663 au8TestInts[i] = (uint8_t)RTRandU32Ex(1, UINT8_MAX);
664 test1<RTCList, uint8_t, uint8_t, uint8_t>("ST: Native type", au8TestInts, RT_ELEMENTS(au8TestInts));
665 test1<RTCMTList, uint8_t, uint8_t, uint8_t>("MT: Native type", au8TestInts, RT_ELEMENTS(au8TestInts));
666
667 uint16_t au16TestInts[s_cTestCount];
668 for (size_t i = 0; i < RT_ELEMENTS(au16TestInts); ++i)
669 au16TestInts[i] = (uint16_t)RTRandU32Ex(1, UINT16_MAX);
670 test1<RTCList, uint16_t, uint16_t, uint16_t>("ST: Native type", au16TestInts, RT_ELEMENTS(au16TestInts));
671 test1<RTCMTList, uint16_t, uint16_t, uint16_t>("MT: Native type", au16TestInts, RT_ELEMENTS(au16TestInts));
672
673 uint32_t au32TestInts[s_cTestCount];
674 for (size_t i = 0; i < RT_ELEMENTS(au32TestInts); ++i)
675 au32TestInts[i] = RTRandU32Ex(1, UINT32_MAX);
676 test1<RTCList, uint32_t, uint32_t, uint32_t>("ST: Native type", au32TestInts, RT_ELEMENTS(au32TestInts));
677 test1<RTCMTList, uint32_t, uint32_t, uint32_t>("MT: Native type", au32TestInts, RT_ELEMENTS(au32TestInts));
678
679 /*
680 * Specialized type.
681 */
682 uint64_t au64TestInts[s_cTestCount];
683 for (size_t i = 0; i < RT_ELEMENTS(au64TestInts); ++i)
684 au64TestInts[i] = RTRandU64Ex(1, UINT64_MAX);
685 test1<RTCList, uint64_t, uint64_t, uint64_t>("ST: Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));
686 test1<RTCMTList, uint64_t, uint64_t, uint64_t>("MT: Specialized type", au64TestInts, RT_ELEMENTS(au64TestInts));
687
688 /*
689 * Big size type (translate to internal pointer list).
690 */
691 test1<RTCList, RTCString, RTCString *, const char *>("ST: Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));
692 test1<RTCMTList, RTCString, RTCString *, const char *>("MT: Class type", g_apszTestStrings, RT_ELEMENTS(g_apszTestStrings));
693
694 /*
695 * Multi-threading test.
696 */
697 test2();
698
699 /*
700 * Summary.
701 */
702 return RTTestSummaryAndDestroy(hTest);
703}
704
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette