On x86 compilers without fastcall, simulate it when invoking traces and un-simulate...
[wine-gecko.git] / xpcom / tests / TestTArray.cpp
bloba3766b6bf99913ceb50e47f8f755d609019b8439
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* vim:set ts=2 sw=2 sts=2 et cindent: */
3 /* ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is C++ array template tests.
18 * The Initial Developer of the Original Code is Google Inc.
19 * Portions created by the Initial Developer are Copyright (C) 2005
20 * the Initial Developer. All Rights Reserved.
22 * Contributor(s):
23 * Darin Fisher <darin@meer.net>
25 * Alternatively, the contents of this file may be used under the terms of
26 * either the GNU General Public License Version 2 or later (the "GPL"), or
27 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
28 * in which case the provisions of the GPL or the LGPL are applicable instead
29 * of those above. If you wish to allow use of your version of this file only
30 * under the terms of either the GPL or the LGPL, and not to allow others to
31 * use your version of this file under the terms of the MPL, indicate your
32 * decision by deleting the provisions above and replace them with the notice
33 * and other provisions required by the GPL or the LGPL. If you do not delete
34 * the provisions above, a recipient may use your version of this file under
35 * the terms of any one of the MPL, the GPL or the LGPL.
37 * ***** END LICENSE BLOCK ***** */
39 #include <stdlib.h>
40 #include <stdio.h>
41 #include "nsTArray.h"
42 #include "nsTPtrArray.h"
43 #include "nsMemory.h"
44 #include "nsAutoPtr.h"
45 #include "nsString.h"
46 #include "nsDirectoryServiceDefs.h"
47 #include "nsDirectoryServiceUtils.h"
48 #include "nsComponentManagerUtils.h"
49 #include "nsXPCOM.h"
50 #include "nsILocalFile.h"
52 namespace TestTArray {
54 // Define this so we can use test_basic_array in test_comptr_array
55 template <class T>
56 inline bool operator<(const nsCOMPtr<T>& lhs, const nsCOMPtr<T>& rhs) {
57 return lhs.get() < rhs.get();
60 //----
62 template <class ElementType>
63 static PRBool test_basic_array(ElementType *data,
64 PRUint32 dataLen,
65 const ElementType& extra) {
66 nsTArray<ElementType> ary;
67 ary.AppendElements(data, dataLen);
68 if (ary.Length() != dataLen) {
69 return PR_FALSE;
71 PRUint32 i;
72 for (i = 0; i < ary.Length(); ++i) {
73 if (ary[i] != data[i])
74 return PR_FALSE;
76 for (i = 0; i < ary.Length(); ++i) {
77 if (ary.SafeElementAt(i, extra) != data[i])
78 return PR_FALSE;
80 if (ary.SafeElementAt(ary.Length(), extra) != extra ||
81 ary.SafeElementAt(ary.Length() * 10, extra) != extra)
82 return PR_FALSE;
83 // ensure sort results in ascending order
84 ary.Sort();
85 for (i = ary.Length(); --i; ) {
86 if (ary[i] < ary[i - 1])
87 return PR_FALSE;
88 if (ary[i] == ary[i - 1])
89 ary.RemoveElementAt(i);
91 for (i = 0; i < ary.Length(); ++i) {
92 if (ary.BinaryIndexOf(ary[i]) != i)
93 return PR_FALSE;
95 if (ary.BinaryIndexOf(extra) != -1)
96 return PR_FALSE;
97 PRUint32 oldLen = ary.Length();
98 ary.RemoveElement(data[dataLen / 2]);
99 if (ary.Length() != (oldLen - 1))
100 return PR_FALSE;
102 PRUint32 index = ary.Length() / 2;
103 if (!ary.InsertElementAt(index, extra))
104 return PR_FALSE;
105 if (ary[index] != extra)
106 return PR_FALSE;
107 if (ary.IndexOf(extra) == PR_UINT32_MAX)
108 return PR_FALSE;
109 if (ary.LastIndexOf(extra) == PR_UINT32_MAX)
110 return PR_FALSE;
111 // ensure proper searching
112 if (ary.IndexOf(extra) > ary.LastIndexOf(extra))
113 return PR_FALSE;
114 if (ary.IndexOf(extra, index) != ary.LastIndexOf(extra, index))
115 return PR_FALSE;
117 nsTArray<ElementType> copy(ary);
118 for (i = 0; i < copy.Length(); ++i) {
119 if (ary[i] != copy[i])
120 return PR_FALSE;
122 if (!ary.AppendElements(copy))
123 return PR_FALSE;
124 PRUint32 cap = ary.Capacity();
125 ary.RemoveElementsAt(copy.Length(), copy.Length());
126 ary.Compact();
127 if (ary.Capacity() == cap)
128 return PR_FALSE;
130 ary.Clear();
131 if (!ary.IsEmpty() || ary.Elements() == nsnull)
132 return PR_FALSE;
133 if (ary.SafeElementAt(0, extra) != extra ||
134 ary.SafeElementAt(10, extra) != extra)
135 return PR_FALSE;
137 ary = copy;
138 for (i = 0; i < copy.Length(); ++i) {
139 if (ary[i] != copy[i])
140 return PR_FALSE;
143 if (!ary.InsertElementsAt(0, copy))
144 return PR_FALSE;
145 ary.RemoveElementsAt(0, copy.Length());
146 for (i = 0; i < copy.Length(); ++i) {
147 if (ary[i] != copy[i])
148 return PR_FALSE;
151 // These shouldn't crash!
152 nsTArray<ElementType> empty;
153 ary.AppendElements(reinterpret_cast<ElementType *>(0), 0);
154 ary.AppendElements(empty);
156 // See bug 324981
157 ary.RemoveElement(extra);
158 ary.RemoveElement(extra);
160 return PR_TRUE;
163 static PRBool test_int_array() {
164 int data[] = {4,6,8,2,4,1,5,7,3};
165 return test_basic_array(data, NS_ARRAY_LENGTH(data), int(14));
168 static PRBool test_int64_array() {
169 PRInt64 data[] = {4,6,8,2,4,1,5,7,3};
170 return test_basic_array(data, NS_ARRAY_LENGTH(data), PRInt64(14));
173 static PRBool test_char_array() {
174 char data[] = {4,6,8,2,4,1,5,7,3};
175 return test_basic_array(data, NS_ARRAY_LENGTH(data), char(14));
178 static PRBool test_uint32_array() {
179 PRUint32 data[] = {4,6,8,2,4,1,5,7,3};
180 return test_basic_array(data, NS_ARRAY_LENGTH(data), PRUint32(14));
183 //----
185 class Object {
186 public:
187 Object() : mNum(0) {
189 Object(const char *str, PRUint32 num) : mStr(str), mNum(num) {
191 Object(const Object& other) : mStr(other.mStr), mNum(other.mNum) {
193 ~Object() {}
195 Object& operator=(const Object& other) {
196 mStr = other.mStr;
197 mNum = other.mNum;
198 return *this;
201 PRBool operator==(const Object& other) const {
202 return mStr == other.mStr && mNum == other.mNum;
205 PRBool operator<(const Object& other) const {
206 // sort based on mStr only
207 return Compare(mStr, other.mStr) < 0;
210 const char *Str() const { return mStr.get(); }
211 PRUint32 Num() const { return mNum; }
213 private:
214 nsCString mStr;
215 PRUint32 mNum;
218 static PRBool test_object_array() {
219 nsTArray<Object> objArray;
220 const char kdata[] = "hello world";
221 PRUint32 i;
222 for (i = 0; i < NS_ARRAY_LENGTH(kdata); ++i) {
223 char x[] = {kdata[i],'\0'};
224 if (!objArray.AppendElement(Object(x, i)))
225 return PR_FALSE;
227 for (i = 0; i < NS_ARRAY_LENGTH(kdata); ++i) {
228 if (objArray[i].Str()[0] != kdata[i])
229 return PR_FALSE;
230 if (objArray[i].Num() != i)
231 return PR_FALSE;
233 objArray.Sort();
234 const char ksorted[] = "\0 dehllloorw";
235 for (i = 0; i < NS_ARRAY_LENGTH(kdata)-1; ++i) {
236 if (objArray[i].Str()[0] != ksorted[i])
237 return PR_FALSE;
239 return PR_TRUE;
242 // nsTArray<nsAutoPtr<T>> is not supported
243 #if 0
244 static PRBool test_autoptr_array() {
245 nsTArray< nsAutoPtr<Object> > objArray;
246 const char kdata[] = "hello world";
247 for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(kdata); ++i) {
248 char x[] = {kdata[i],'\0'};
249 nsAutoPtr<Object> obj(new Object(x,i));
250 if (!objArray.AppendElement(obj)) // XXX does not call copy-constructor for nsAutoPtr!!!
251 return PR_FALSE;
252 if (obj.get() == nsnull)
253 return PR_FALSE;
254 obj.forget(); // the array now owns the reference
256 for (PRUint32 i = 0; i < NS_ARRAY_LENGTH(kdata); ++i) {
257 if (objArray[i]->Str()[0] != kdata[i])
258 return PR_FALSE;
259 if (objArray[i]->Num() != i)
260 return PR_FALSE;
262 return PR_TRUE;
264 #endif
266 //----
268 static PRBool operator==(const nsCString &a, const char *b) {
269 return a.Equals(b);
272 static PRBool test_string_array() {
273 nsTArray<nsCString> strArray;
274 const char kdata[] = "hello world";
275 PRUint32 i;
276 for (i = 0; i < NS_ARRAY_LENGTH(kdata); ++i) {
277 if (!strArray.AppendElement(nsCString(kdata[i])))
278 return PR_FALSE;
280 for (i = 0; i < NS_ARRAY_LENGTH(kdata); ++i) {
281 if (strArray[i].CharAt(0) != kdata[i])
282 return PR_FALSE;
285 const char kextra[] = "foo bar";
286 PRUint32 oldLen = strArray.Length();
287 if (!strArray.AppendElement(kextra))
288 return PR_FALSE;
289 strArray.RemoveElement(kextra);
290 if (oldLen != strArray.Length())
291 return PR_FALSE;
293 if (strArray.IndexOf("e") != 1)
294 return PR_FALSE;
296 strArray.Sort();
297 const char ksorted[] = "\0 dehllloorw";
298 for (i = NS_ARRAY_LENGTH(kdata); i--; ) {
299 if (strArray[i].CharAt(0) != ksorted[i])
300 return PR_FALSE;
301 if (i > 0 && strArray[i] == strArray[i - 1])
302 strArray.RemoveElementAt(i);
304 for (i = 0; i < strArray.Length(); ++i) {
305 if (strArray.BinaryIndexOf(strArray[i]) != i)
306 return PR_FALSE;
308 if (strArray.BinaryIndexOf(EmptyCString()) != -1)
309 return PR_FALSE;
311 nsCString rawArray[NS_ARRAY_LENGTH(kdata)-1];
312 for (i = 0; i < NS_ARRAY_LENGTH(rawArray); ++i)
313 rawArray[i].Assign(kdata + i); // substrings of kdata
314 return test_basic_array(rawArray, NS_ARRAY_LENGTH(rawArray),
315 nsCString("foopy"));
318 //----
320 typedef nsCOMPtr<nsIFile> FilePointer;
322 class nsFileNameComparator {
323 public:
324 PRBool Equals(const FilePointer &a, const char *b) const {
325 nsCAutoString name;
326 a->GetNativeLeafName(name);
327 return name.Equals(b);
331 static PRBool test_comptr_array() {
332 FilePointer tmpDir;
333 NS_GetSpecialDirectory(NS_OS_TEMP_DIR, getter_AddRefs(tmpDir));
334 if (!tmpDir)
335 return PR_FALSE;
336 const char *kNames[] = {
337 "foo.txt", "bar.html", "baz.gif"
339 nsTArray<FilePointer> fileArray;
340 PRUint32 i;
341 for (i = 0; i < NS_ARRAY_LENGTH(kNames); ++i) {
342 FilePointer f;
343 tmpDir->Clone(getter_AddRefs(f));
344 if (!f)
345 return PR_FALSE;
346 if (NS_FAILED(f->AppendNative(nsDependentCString(kNames[i]))))
347 return PR_FALSE;
348 fileArray.AppendElement(f);
351 if (fileArray.IndexOf(kNames[1], 0, nsFileNameComparator()) != 1)
352 return PR_FALSE;
354 // It's unclear what 'operator<' means for nsCOMPtr, but whatever...
355 return test_basic_array(fileArray.Elements(), fileArray.Length(),
356 tmpDir);
359 //----
361 class RefcountedObject {
362 public:
363 RefcountedObject() : rc(0) {}
364 void AddRef() {
365 ++rc;
367 void Release() {
368 if (--rc == 0)
369 delete this;
371 ~RefcountedObject() {}
372 private:
373 PRInt32 rc;
376 static PRBool test_refptr_array() {
377 PRBool rv = PR_TRUE;
379 nsTArray< nsRefPtr<RefcountedObject> > objArray;
381 RefcountedObject *a = new RefcountedObject(); a->AddRef();
382 RefcountedObject *b = new RefcountedObject(); b->AddRef();
383 RefcountedObject *c = new RefcountedObject(); c->AddRef();
385 objArray.AppendElement(a);
386 objArray.AppendElement(b);
387 objArray.AppendElement(c);
389 if (objArray.IndexOf(b) != 1)
390 rv = PR_FALSE;
392 a->Release();
393 b->Release();
394 c->Release();
395 return rv;
398 //----
400 static PRBool test_ptrarray() {
401 nsTPtrArray<PRUint32> ary;
402 if (ary.SafeElementAt(0) != nsnull)
403 return PR_FALSE;
404 if (ary.SafeElementAt(1000) != nsnull)
405 return PR_FALSE;
406 PRUint32 a = 10;
407 ary.AppendElement(&a);
408 if (*ary[0] != a)
409 return PR_FALSE;
410 if (*ary.SafeElementAt(0) != a)
411 return PR_FALSE;
413 nsTPtrArray<const PRUint32> cary;
414 if (cary.SafeElementAt(0) != nsnull)
415 return PR_FALSE;
416 if (cary.SafeElementAt(1000) != nsnull)
417 return PR_FALSE;
418 const PRUint32 b = 14;
419 cary.AppendElement(&a);
420 cary.AppendElement(&b);
421 if (*cary[0] != a || *cary[1] != b)
422 return PR_FALSE;
423 if (*cary.SafeElementAt(0) != a || *cary.SafeElementAt(1) != b)
424 return PR_FALSE;
426 return PR_TRUE;
429 //----
431 // This test relies too heavily on the existance of DebugGetHeader to be
432 // useful in non-debug builds.
433 #ifdef DEBUG
434 static PRBool test_autoarray() {
435 PRUint32 data[] = {4,6,8,2,4,1,5,7,3};
436 nsAutoTArray<PRUint32, NS_ARRAY_LENGTH(data)> array;
438 void* hdr = array.DebugGetHeader();
439 if (hdr == nsTArray<PRUint32>().DebugGetHeader())
440 return PR_FALSE;
441 if (hdr == nsAutoTArray<PRUint32, NS_ARRAY_LENGTH(data)>().DebugGetHeader())
442 return PR_FALSE;
444 array.AppendElement(1u);
445 if (hdr != array.DebugGetHeader())
446 return PR_FALSE;
448 array.RemoveElement(1u);
449 array.AppendElements(data, NS_ARRAY_LENGTH(data));
450 if (hdr != array.DebugGetHeader())
451 return PR_FALSE;
453 array.AppendElement(2u);
454 if (hdr == array.DebugGetHeader())
455 return PR_FALSE;
457 array.Clear();
458 array.Compact();
459 if (hdr != array.DebugGetHeader())
460 return PR_FALSE;
461 array.AppendElements(data, NS_ARRAY_LENGTH(data));
462 if (hdr != array.DebugGetHeader())
463 return PR_FALSE;
465 nsTArray<PRUint32> array2;
466 void* emptyHdr = array2.DebugGetHeader();
467 array.SwapElements(array2);
468 if (emptyHdr == array.DebugGetHeader())
469 return PR_FALSE;
470 if (hdr == array2.DebugGetHeader())
471 return PR_FALSE;
472 PRUint32 i;
473 for (i = 0; i < NS_ARRAY_LENGTH(data); ++i) {
474 if (array2[i] != data[i])
475 return PR_FALSE;
477 if (!array.IsEmpty())
478 return PR_FALSE;
480 array.Compact();
481 array.AppendElements(data, NS_ARRAY_LENGTH(data));
482 PRUint32 data3[] = {5, 7, 11};
483 nsAutoTArray<PRUint32, NS_ARRAY_LENGTH(data3)> array3;
484 array3.AppendElements(data3, NS_ARRAY_LENGTH(data3));
485 array.SwapElements(array3);
486 for (i = 0; i < NS_ARRAY_LENGTH(data); ++i) {
487 if (array3[i] != data[i])
488 return PR_FALSE;
490 for (i = 0; i < NS_ARRAY_LENGTH(data3); ++i) {
491 if (array[i] != data3[i])
492 return PR_FALSE;
495 return PR_TRUE;
497 #endif
499 //----
501 typedef PRBool (*TestFunc)();
502 #define DECL_TEST(name) { #name, name }
504 static const struct Test {
505 const char* name;
506 TestFunc func;
507 } tests[] = {
508 DECL_TEST(test_int_array),
509 DECL_TEST(test_int64_array),
510 DECL_TEST(test_char_array),
511 DECL_TEST(test_uint32_array),
512 DECL_TEST(test_object_array),
513 DECL_TEST(test_string_array),
514 DECL_TEST(test_comptr_array),
515 DECL_TEST(test_refptr_array),
516 DECL_TEST(test_ptrarray),
517 #ifdef DEBUG
518 DECL_TEST(test_autoarray),
519 #endif
520 { nsnull, nsnull }
525 using namespace TestTArray;
527 int main(int argc, char **argv) {
528 int count = 1;
529 if (argc > 1)
530 count = atoi(argv[1]);
532 if (NS_FAILED(NS_InitXPCOM2(nsnull, nsnull, nsnull)))
533 return -1;
535 while (count--) {
536 for (const Test* t = tests; t->name != nsnull; ++t) {
537 printf("%25s : %s\n", t->name, t->func() ? "SUCCESS" : "FAILURE");
541 NS_ShutdownXPCOM(nsnull);
542 return 0;