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
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.
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 ***** */
42 #include "nsTPtrArray.h"
44 #include "nsAutoPtr.h"
46 #include "nsDirectoryServiceDefs.h"
47 #include "nsDirectoryServiceUtils.h"
48 #include "nsComponentManagerUtils.h"
50 #include "nsILocalFile.h"
52 namespace TestTArray
{
54 // Define this so we can use test_basic_array in test_comptr_array
56 inline bool operator<(const nsCOMPtr
<T
>& lhs
, const nsCOMPtr
<T
>& rhs
) {
57 return lhs
.get() < rhs
.get();
62 template <class ElementType
>
63 static PRBool
test_basic_array(ElementType
*data
,
65 const ElementType
& extra
) {
66 nsTArray
<ElementType
> ary
;
67 ary
.AppendElements(data
, dataLen
);
68 if (ary
.Length() != dataLen
) {
75 for (i
= 0; i
< ary
.Length(); ++i
) {
76 if (ary
[i
] != data
[i
])
79 for (i
= 0; i
< ary
.Length(); ++i
) {
80 if (ary
.SafeElementAt(i
, extra
) != data
[i
])
83 if (ary
.SafeElementAt(ary
.Length(), extra
) != extra
||
84 ary
.SafeElementAt(ary
.Length() * 10, extra
) != extra
)
86 // ensure sort results in ascending order
89 if (ary
.GreatestIndexLtEq(extra
, k
))
91 for (i
= 0; i
< ary
.Length(); ++i
) {
92 if (!ary
.GreatestIndexLtEq(ary
[i
], k
))
98 for (i
= ary
.Length(); --i
; ) {
99 if (ary
[i
] < ary
[i
- 1])
101 if (ary
[i
] == ary
[i
- 1])
102 ary
.RemoveElementAt(i
);
107 for (i
= 0; i
< ary
.Length(); ++i
) {
108 if (ary
.BinaryIndexOf(ary
[i
]) != i
)
111 if (ary
.BinaryIndexOf(extra
) != ary
.NoIndex
)
113 PRUint32 oldLen
= ary
.Length();
114 ary
.RemoveElement(data
[dataLen
/ 2]);
115 if (ary
.Length() != (oldLen
- 1))
120 PRUint32 index
= ary
.Length() / 2;
121 if (!ary
.InsertElementAt(index
, extra
))
125 if (ary
[index
] != extra
)
127 if (ary
.IndexOf(extra
) == PR_UINT32_MAX
)
129 if (ary
.LastIndexOf(extra
) == PR_UINT32_MAX
)
131 // ensure proper searching
132 if (ary
.IndexOf(extra
) > ary
.LastIndexOf(extra
))
134 if (ary
.IndexOf(extra
, index
) != ary
.LastIndexOf(extra
, index
))
137 nsTArray
<ElementType
> copy(ary
);
140 for (i
= 0; i
< copy
.Length(); ++i
) {
141 if (ary
[i
] != copy
[i
])
144 if (!ary
.AppendElements(copy
))
146 PRUint32 cap
= ary
.Capacity();
147 ary
.RemoveElementsAt(copy
.Length(), copy
.Length());
149 if (ary
.Capacity() == cap
)
153 if (!ary
.IsEmpty() || ary
.Elements() == nsnull
)
155 if (!(ary
== nsTArray
<ElementType
>()))
159 if (ary
.SafeElementAt(0, extra
) != extra
||
160 ary
.SafeElementAt(10, extra
) != extra
)
166 for (i
= 0; i
< copy
.Length(); ++i
) {
167 if (ary
[i
] != copy
[i
])
171 if (!ary
.InsertElementsAt(0, copy
))
175 ary
.RemoveElementsAt(0, copy
.Length());
176 for (i
= 0; i
< copy
.Length(); ++i
) {
177 if (ary
[i
] != copy
[i
])
181 // These shouldn't crash!
182 nsTArray
<ElementType
> empty
;
183 ary
.AppendElements(reinterpret_cast<ElementType
*>(0), 0);
184 ary
.AppendElements(empty
);
187 ary
.RemoveElement(extra
);
188 ary
.RemoveElement(extra
);
193 static PRBool
test_int_array() {
194 int data
[] = {4,6,8,2,4,1,5,7,3};
195 return test_basic_array(data
, NS_ARRAY_LENGTH(data
), int(14));
198 static PRBool
test_int64_array() {
199 PRInt64 data
[] = {4,6,8,2,4,1,5,7,3};
200 return test_basic_array(data
, NS_ARRAY_LENGTH(data
), PRInt64(14));
203 static PRBool
test_char_array() {
204 char data
[] = {4,6,8,2,4,1,5,7,3};
205 return test_basic_array(data
, NS_ARRAY_LENGTH(data
), char(14));
208 static PRBool
test_uint32_array() {
209 PRUint32 data
[] = {4,6,8,2,4,1,5,7,3};
210 return test_basic_array(data
, NS_ARRAY_LENGTH(data
), PRUint32(14));
219 Object(const char *str
, PRUint32 num
) : mStr(str
), mNum(num
) {
221 Object(const Object
& other
) : mStr(other
.mStr
), mNum(other
.mNum
) {
225 Object
& operator=(const Object
& other
) {
231 PRBool
operator==(const Object
& other
) const {
232 return mStr
== other
.mStr
&& mNum
== other
.mNum
;
235 PRBool
operator<(const Object
& other
) const {
236 // sort based on mStr only
237 return Compare(mStr
, other
.mStr
) < 0;
240 const char *Str() const { return mStr
.get(); }
241 PRUint32
Num() const { return mNum
; }
248 static PRBool
test_object_array() {
249 nsTArray
<Object
> objArray
;
250 const char kdata
[] = "hello world";
252 for (i
= 0; i
< NS_ARRAY_LENGTH(kdata
); ++i
) {
253 char x
[] = {kdata
[i
],'\0'};
254 if (!objArray
.AppendElement(Object(x
, i
)))
257 for (i
= 0; i
< NS_ARRAY_LENGTH(kdata
); ++i
) {
258 if (objArray
[i
].Str()[0] != kdata
[i
])
260 if (objArray
[i
].Num() != i
)
264 const char ksorted
[] = "\0 dehllloorw";
265 for (i
= 0; i
< NS_ARRAY_LENGTH(kdata
)-1; ++i
) {
266 if (objArray
[i
].Str()[0] != ksorted
[i
])
272 // nsTArray<nsAutoPtr<T>> is not supported
274 static PRBool
test_autoptr_array() {
275 nsTArray
< nsAutoPtr
<Object
> > objArray
;
276 const char kdata
[] = "hello world";
277 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(kdata
); ++i
) {
278 char x
[] = {kdata
[i
],'\0'};
279 nsAutoPtr
<Object
> obj(new Object(x
,i
));
280 if (!objArray
.AppendElement(obj
)) // XXX does not call copy-constructor for nsAutoPtr!!!
282 if (obj
.get() == nsnull
)
284 obj
.forget(); // the array now owns the reference
286 for (PRUint32 i
= 0; i
< NS_ARRAY_LENGTH(kdata
); ++i
) {
287 if (objArray
[i
]->Str()[0] != kdata
[i
])
289 if (objArray
[i
]->Num() != i
)
298 static PRBool
operator==(const nsCString
&a
, const char *b
) {
302 static PRBool
test_string_array() {
303 nsTArray
<nsCString
> strArray
;
304 const char kdata
[] = "hello world";
306 for (i
= 0; i
< NS_ARRAY_LENGTH(kdata
); ++i
) {
307 if (!strArray
.AppendElement(nsCString(kdata
[i
])))
310 for (i
= 0; i
< NS_ARRAY_LENGTH(kdata
); ++i
) {
311 if (strArray
[i
].CharAt(0) != kdata
[i
])
315 const char kextra
[] = "foo bar";
316 PRUint32 oldLen
= strArray
.Length();
317 if (!strArray
.AppendElement(kextra
))
319 strArray
.RemoveElement(kextra
);
320 if (oldLen
!= strArray
.Length())
323 if (strArray
.IndexOf("e") != 1)
327 const char ksorted
[] = "\0 dehllloorw";
328 for (i
= NS_ARRAY_LENGTH(kdata
); i
--; ) {
329 if (strArray
[i
].CharAt(0) != ksorted
[i
])
331 if (i
> 0 && strArray
[i
] == strArray
[i
- 1])
332 strArray
.RemoveElementAt(i
);
334 for (i
= 0; i
< strArray
.Length(); ++i
) {
335 if (strArray
.BinaryIndexOf(strArray
[i
]) != i
)
338 if (strArray
.BinaryIndexOf(EmptyCString()) != strArray
.NoIndex
)
341 nsCString rawArray
[NS_ARRAY_LENGTH(kdata
)-1];
342 for (i
= 0; i
< NS_ARRAY_LENGTH(rawArray
); ++i
)
343 rawArray
[i
].Assign(kdata
+ i
); // substrings of kdata
344 return test_basic_array(rawArray
, NS_ARRAY_LENGTH(rawArray
),
350 typedef nsCOMPtr
<nsIFile
> FilePointer
;
352 class nsFileNameComparator
{
354 PRBool
Equals(const FilePointer
&a
, const char *b
) const {
356 a
->GetNativeLeafName(name
);
357 return name
.Equals(b
);
361 static PRBool
test_comptr_array() {
363 NS_GetSpecialDirectory(NS_OS_TEMP_DIR
, getter_AddRefs(tmpDir
));
366 const char *kNames
[] = {
367 "foo.txt", "bar.html", "baz.gif"
369 nsTArray
<FilePointer
> fileArray
;
371 for (i
= 0; i
< NS_ARRAY_LENGTH(kNames
); ++i
) {
373 tmpDir
->Clone(getter_AddRefs(f
));
376 if (NS_FAILED(f
->AppendNative(nsDependentCString(kNames
[i
]))))
378 fileArray
.AppendElement(f
);
381 if (fileArray
.IndexOf(kNames
[1], 0, nsFileNameComparator()) != 1)
384 // It's unclear what 'operator<' means for nsCOMPtr, but whatever...
385 return test_basic_array(fileArray
.Elements(), fileArray
.Length(),
391 class RefcountedObject
{
393 RefcountedObject() : rc(0) {}
401 ~RefcountedObject() {}
406 static PRBool
test_refptr_array() {
409 nsTArray
< nsRefPtr
<RefcountedObject
> > objArray
;
411 RefcountedObject
*a
= new RefcountedObject(); a
->AddRef();
412 RefcountedObject
*b
= new RefcountedObject(); b
->AddRef();
413 RefcountedObject
*c
= new RefcountedObject(); c
->AddRef();
415 objArray
.AppendElement(a
);
416 objArray
.AppendElement(b
);
417 objArray
.AppendElement(c
);
419 if (objArray
.IndexOf(b
) != 1)
430 static PRBool
test_ptrarray() {
431 nsTPtrArray
<PRUint32
> ary
;
432 if (ary
.SafeElementAt(0) != nsnull
)
434 if (ary
.SafeElementAt(1000) != nsnull
)
437 ary
.AppendElement(&a
);
440 if (*ary
.SafeElementAt(0) != a
)
443 nsTPtrArray
<const PRUint32
> cary
;
444 if (cary
.SafeElementAt(0) != nsnull
)
446 if (cary
.SafeElementAt(1000) != nsnull
)
448 const PRUint32 b
= 14;
449 cary
.AppendElement(&a
);
450 cary
.AppendElement(&b
);
451 if (*cary
[0] != a
|| *cary
[1] != b
)
453 if (*cary
.SafeElementAt(0) != a
|| *cary
.SafeElementAt(1) != b
)
461 // This test relies too heavily on the existence of DebugGetHeader to be
462 // useful in non-debug builds.
464 static PRBool
test_autoarray() {
465 PRUint32 data
[] = {4,6,8,2,4,1,5,7,3};
466 nsAutoTArray
<PRUint32
, NS_ARRAY_LENGTH(data
)> array
;
468 void* hdr
= array
.DebugGetHeader();
469 if (hdr
== nsTArray
<PRUint32
>().DebugGetHeader())
471 if (hdr
== nsAutoTArray
<PRUint32
, NS_ARRAY_LENGTH(data
)>().DebugGetHeader())
474 array
.AppendElement(1u);
475 if (hdr
!= array
.DebugGetHeader())
478 array
.RemoveElement(1u);
479 array
.AppendElements(data
, NS_ARRAY_LENGTH(data
));
480 if (hdr
!= array
.DebugGetHeader())
483 array
.AppendElement(2u);
484 if (hdr
== array
.DebugGetHeader())
489 if (hdr
!= array
.DebugGetHeader())
491 array
.AppendElements(data
, NS_ARRAY_LENGTH(data
));
492 if (hdr
!= array
.DebugGetHeader())
495 nsTArray
<PRUint32
> array2
;
496 void* emptyHdr
= array2
.DebugGetHeader();
497 array
.SwapElements(array2
);
498 if (emptyHdr
== array
.DebugGetHeader())
500 if (hdr
== array2
.DebugGetHeader())
503 for (i
= 0; i
< NS_ARRAY_LENGTH(data
); ++i
) {
504 if (array2
[i
] != data
[i
])
507 if (!array
.IsEmpty())
511 array
.AppendElements(data
, NS_ARRAY_LENGTH(data
));
512 PRUint32 data3
[] = {5, 7, 11};
513 nsAutoTArray
<PRUint32
, NS_ARRAY_LENGTH(data3
)> array3
;
514 array3
.AppendElements(data3
, NS_ARRAY_LENGTH(data3
));
515 array
.SwapElements(array3
);
516 for (i
= 0; i
< NS_ARRAY_LENGTH(data
); ++i
) {
517 if (array3
[i
] != data
[i
])
520 for (i
= 0; i
< NS_ARRAY_LENGTH(data3
); ++i
) {
521 if (array
[i
] != data3
[i
])
531 // IndexOf used to potentially scan beyond the end of the array. Test for
532 // this incorrect behavior by adding a value (5), removing it, then seeing
533 // if IndexOf finds it.
534 static PRBool
test_indexof() {
536 array
.AppendElement(0);
537 // add and remove the 5
538 array
.AppendElement(5);
539 array
.RemoveElementAt(1);
540 // we should not find the 5!
541 return array
.IndexOf(5, 1) == array
.NoIndex
;
546 template <class Array
>
547 static PRBool
is_heap(const Array
& ary
, PRUint32 len
) {
549 while (index
< len
) {
550 if (ary
[index
] > ary
[(index
- 1) >> 1])
557 static PRBool
test_heap() {
558 const int data
[] = {4,6,8,2,4,1,5,7,3};
560 ary
.AppendElements(data
, NS_ARRAY_LENGTH(data
));
561 // make a heap and make sure it's a heap
563 if (!is_heap(ary
, NS_ARRAY_LENGTH(data
)))
565 // pop the root and make sure it's still a heap
568 if (!is_heap(ary
, NS_ARRAY_LENGTH(data
) - 1))
570 // push the previously poped value back on and make sure it's still a heap
572 if (!is_heap(ary
, NS_ARRAY_LENGTH(data
)))
574 // make sure the heap looks like what we expect
575 const int expected_data
[] = {8,7,5,6,4,1,4,2,3};
577 for (index
= 0; index
< NS_ARRAY_LENGTH(data
); index
++)
578 if (ary
[index
] != expected_data
[index
])
585 typedef PRBool (*TestFunc
)();
586 #define DECL_TEST(name) { #name, name }
588 static const struct Test
{
592 DECL_TEST(test_int_array
),
593 DECL_TEST(test_int64_array
),
594 DECL_TEST(test_char_array
),
595 DECL_TEST(test_uint32_array
),
596 DECL_TEST(test_object_array
),
597 DECL_TEST(test_string_array
),
598 DECL_TEST(test_comptr_array
),
599 DECL_TEST(test_refptr_array
),
600 DECL_TEST(test_ptrarray
),
602 DECL_TEST(test_autoarray
),
604 DECL_TEST(test_indexof
),
605 DECL_TEST(test_heap
),
611 using namespace TestTArray
;
613 int main(int argc
, char **argv
) {
616 count
= atoi(argv
[1]);
618 if (NS_FAILED(NS_InitXPCOM2(nsnull
, nsnull
, nsnull
)))
622 for (const Test
* t
= tests
; t
->name
!= nsnull
; ++t
) {
623 printf("%25s : %s\n", t
->name
, t
->func() ? "SUCCESS" : "FAILURE");
627 NS_ShutdownXPCOM(nsnull
);